// NewServiceServingCertUpdateController creates a new ServiceServingCertUpdateController. // TODO this should accept a shared informer func NewServiceServingCertUpdateController(serviceClient kcoreclient.ServicesGetter, secretClient kcoreclient.SecretsGetter, ca *crypto.CA, dnsSuffix string, resyncInterval time.Duration) *ServiceServingCertUpdateController { sc := &ServiceServingCertUpdateController{ secretClient: secretClient, queue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()), ca: ca, dnsSuffix: dnsSuffix, // TODO base the expiry time on a percentage of the time for the lifespan of the cert minTimeLeftForCert: 1 * time.Hour, } sc.serviceCache, sc.serviceController = framework.NewInformer( &cache.ListWatch{ ListFunc: func(options kapi.ListOptions) (runtime.Object, error) { return serviceClient.Services(kapi.NamespaceAll).List(options) }, WatchFunc: func(options kapi.ListOptions) (watch.Interface, error) { return serviceClient.Services(kapi.NamespaceAll).Watch(options) }, }, &kapi.Service{}, resyncInterval, framework.ResourceEventHandlerFuncs{}, ) sc.serviceHasSynced = sc.serviceController.HasSynced sc.secretCache, sc.secretController = framework.NewInformer( &cache.ListWatch{ ListFunc: func(options kapi.ListOptions) (runtime.Object, error) { return sc.secretClient.Secrets(kapi.NamespaceAll).List(options) }, WatchFunc: func(options kapi.ListOptions) (watch.Interface, error) { return sc.secretClient.Secrets(kapi.NamespaceAll).Watch(options) }, }, &kapi.Secret{}, resyncInterval, framework.ResourceEventHandlerFuncs{ AddFunc: sc.addSecret, UpdateFunc: sc.updateSecret, }, ) sc.secretHasSynced = sc.secretController.HasSynced sc.syncHandler = sc.syncSecret return sc }
func NewListWatchServiceLookup(svcGetter kcoreclient.ServicesGetter, resync time.Duration) ServiceLookup { svcStore := cache.NewStore(cache.MetaNamespaceKeyFunc) lw := &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return svcGetter.Services(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return svcGetter.Services(api.NamespaceAll).Watch(options) }, } cache.NewReflector(lw, &api.Service{}, svcStore, resync).Run() return &serviceLWLookup{ store: svcStore, } }
func persistService(client kcoreclient.ServicesGetter, service *kapi.Service, targetStatus bool) error { backoff := wait.Backoff{ Steps: clientRetryCount, Duration: clientRetryInterval, Factor: clientRetryFactor, } return wait.ExponentialBackoff(backoff, func() (bool, error) { var err error if targetStatus { _, err = client.Services(service.Namespace).UpdateStatus(service) } else { _, err = client.Services(service.Namespace).Update(service) } switch { case err == nil: return true, nil case kerrors.IsNotFound(err): // If the service no longer exists, we don't want to recreate // it. Just bail out so that we can process the delete, which // we should soon be receiving if we haven't already. glog.V(5).Infof("Not persisting update to service '%s/%s' that no longer exists: %v", service.Namespace, service.Name, err) return true, nil case kerrors.IsConflict(err): // TODO: Try to resolve the conflict if the change was // unrelated to load balancer status. For now, just rely on // the fact that we'll also process the update that caused the // resource version to change. glog.V(5).Infof("Not persisting update to service '%s/%s' that has been changed since we received it: %v", service.Namespace, service.Name, err) return true, nil default: err = fmt.Errorf("Failed to persist updated LoadBalancerStatus to service '%s/%s': %v", service.Namespace, service.Name, err) return false, err } }) }