func (rc *RouteController) Run(syncPeriod time.Duration) { go util.Until(func() { if err := rc.reconcileNodeRoutes(); err != nil { glog.Errorf("Couldn't reconcile node routes: %v", err) } }, syncPeriod, util.NeverStop) }
// Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set). func (s *ProxyServer) Run(_ []string) error { // remove iptables rules and exit if s.Config.CleanupAndExit { encounteredError := userspace.CleanupLeftovers(s.IptInterface) encounteredError = iptables.CleanupLeftovers(s.IptInterface) || encounteredError if encounteredError { return errors.New("Encountered an error while tearing down rules.") } return nil } // Birth Cry after the birth is successful s.birthCry() // Start up Healthz service if requested if s.Config.HealthzPort > 0 { go util.Until(func() { err := http.ListenAndServe(s.Config.HealthzBindAddress.String()+":"+strconv.Itoa(s.Config.HealthzPort), nil) if err != nil { glog.Errorf("Starting health server failed: %v", err) } }, 5*time.Second, util.NeverStop) } // Just loop forever for now... s.Proxier.SyncLoop() return nil }
// RunUntil starts the controller until the provided ch is closed. func (c *Repair) RunUntil(ch chan struct{}) { util.Until(func() { if err := c.RunOnce(); err != nil { util.HandleError(err) } }, c.interval, ch) }
// RunKubernetesService periodically updates the kubernetes service func (c *Controller) RunKubernetesService(ch chan struct{}) { util.Until(func() { if err := c.UpdateKubernetesService(); err != nil { util.HandleError(fmt.Errorf("unable to sync kubernetes service: %v", err)) } }, c.EndpointInterval, ch) }
func (cm *containerManagerImpl) Start() error { // Setup the node if err := cm.setupNode(); err != nil { return err } // Don't run a background thread if there are no ensureStateFuncs. numEnsureStateFuncs := 0 for _, cont := range cm.systemContainers { if cont.ensureStateFunc != nil { numEnsureStateFuncs++ } } if numEnsureStateFuncs == 0 { return nil } // Run ensure state functions every minute. go util.Until(func() { for _, cont := range cm.systemContainers { if cont.ensureStateFunc != nil { if err := cont.ensureStateFunc(cont.manager); err != nil { glog.Warningf("[ContainerManager] Failed to ensure state of %q: %v", cont.name, err) } } } }, time.Minute, util.NeverStop) return nil }
func (a *HorizontalController) Run(syncPeriod time.Duration) { go util.Until(func() { if err := a.reconcileAutoscalers(); err != nil { glog.Errorf("Couldn't reconcile horizontal pod autoscalers: %v", err) } }, syncPeriod, util.NeverStop) }
func startKubelet(k KubeletBootstrap, podCfg *config.PodConfig, kc *KubeletConfig) { // start the kubelet go util.Until(func() { k.Run(podCfg.Updates()) }, 0, util.NeverStop) // start the kubelet server if kc.EnableServer { go util.Until(func() { k.ListenAndServe(kc.Address, kc.Port, kc.TLSOptions, kc.EnableDebuggingHandlers) }, 0, util.NeverStop) } if kc.ReadOnlyPort > 0 { go util.Until(func() { k.ListenAndServeReadOnly(kc.Address, kc.ReadOnlyPort) }, 0, util.NeverStop) } }
func (d *DeploymentController) Run(syncPeriod time.Duration) { go util.Until(func() { errs := d.reconcileDeployments() for _, err := range errs { glog.Errorf("Failed to reconcile: %v", err) } }, syncPeriod, util.NeverStop) }
func main() { clientConfig := kubectl_util.DefaultClientConfig(flags) flags.Parse(os.Args) cfg := parseCfg(*config, *lbDefAlgorithm) if len(*tcpServices) == 0 { glog.Infof("All tcp/https services will be ignored.") } var kubeClient *unversioned.Client var err error defErrorPage := newStaticPageHandler(*errorPage, defaultErrorPage) if defErrorPage == nil { glog.Fatalf("Failed to load the default error page") } go registerHandlers(defErrorPage) proc.StartReaper() if *startSyslog { cfg.startSyslog = true _, err = newSyslogServer("/var/run/haproxy.log.socket") if err != nil { glog.Fatalf("Failed to start syslog server: %v", err) } } if *cluster { if kubeClient, err = unversioned.NewInCluster(); err != nil { glog.Fatalf("Failed to create client: %v", err) } } else { config, err := clientConfig.ClientConfig() if err != nil { glog.Fatalf("error connecting to the client: %v", err) } kubeClient, err = unversioned.New(config) } namespace, specified, err := clientConfig.Namespace() if err != nil { glog.Fatalf("unexpected error: %v", err) } if !specified { namespace = "default" } // TODO: Handle multiple namespaces lbc := newLoadBalancerController(cfg, kubeClient, namespace) go lbc.epController.Run(util.NeverStop) go lbc.svcController.Run(util.NeverStop) if *dry { dryRun(lbc) } else { lbc.cfg.reload() util.Until(lbc.worker, time.Second, util.NeverStop) } }
// NewSerializedImagePuller takes an event recorder and container runtime to create a // image puller that wraps the container runtime's PullImage interface. // Pulls one image at a time. // Issue #10959 has the rationale behind serializing image pulls. func NewSerializedImagePuller(recorder record.EventRecorder, runtime Runtime) ImagePuller { imagePuller := &serializedImagePuller{ recorder: recorder, runtime: runtime, pullRequests: make(chan *imagePullRequest, 10), } go util.Until(imagePuller.pullImages, time.Second, util.NeverStop) return imagePuller }
func NewSourceFile(path string, nodeName string, period time.Duration, updates chan<- interface{}) { config := &sourceFile{ path: path, nodeName: nodeName, updates: updates, } glog.V(1).Infof("Watching path %q", path) go util.Until(config.run, period, util.NeverStop) }
func (c *SSHTunneler) setupSecureProxy(user, privateKeyfile, publicKeyfile string) { // Sync loop to ensure that the SSH key has been installed. go util.Until(func() { if c.InstallSSHKey == nil { glog.Error("Won't attempt to install ssh key: InstallSSHKey function is nil") return } key, err := util.ParsePublicKeyFromFile(publicKeyfile) if err != nil { glog.Errorf("Failed to load public key: %v", err) return } keyData, err := util.EncodeSSHKey(key) if err != nil { glog.Errorf("Failed to encode public key: %v", err) return } if err := c.InstallSSHKey(user, keyData); err != nil { glog.Errorf("Failed to install ssh key: %v", err) } }, 5*time.Minute, c.stopChan) // Sync loop for tunnels // TODO: switch this to watch. go util.Until(func() { if err := c.loadTunnels(user, privateKeyfile); err != nil { glog.Errorf("Failed to load SSH Tunnels: %v", err) } if c.tunnels != nil && c.tunnels.Len() != 0 { // Sleep for 10 seconds if we have some tunnels. // TODO (cjcullen): tunnels can lag behind actually existing nodes. time.Sleep(9 * time.Second) } }, 1*time.Second, c.stopChan) // Refresh loop for tunnels // TODO: could make this more controller-ish go util.Until(func() { time.Sleep(5 * time.Minute) if err := c.refreshTunnels(user, privateKeyfile); err != nil { glog.Errorf("Failed to refresh SSH Tunnels: %v", err) } }, 0*time.Second, c.stopChan) }
func NewSourceURL(url string, header http.Header, nodeName string, period time.Duration, updates chan<- interface{}) { config := &sourceURL{ url: url, header: header, nodeName: nodeName, updates: updates, data: nil, } glog.V(1).Infof("Watching URL %s", url) go util.Until(config.run, period, util.NeverStop) }
// Run begins watching and syncing. func (rm *ReplicationManager) Run(workers int, stopCh <-chan struct{}) { defer util.HandleCrash() go rm.rcController.Run(stopCh) go rm.podController.Run(stopCh) for i := 0; i < workers; i++ { go util.Until(rm.worker, time.Second, stopCh) } <-stopCh glog.Infof("Shutting down RC Manager") rm.queue.ShutDown() }
// Run the main goroutine responsible for watching and syncing jobs. func (jm *JobController) Run(workers int, stopCh <-chan struct{}) { defer util.HandleCrash() go jm.jobController.Run(stopCh) go jm.podController.Run(stopCh) for i := 0; i < workers; i++ { go util.Until(jm.worker, time.Second, stopCh) } <-stopCh glog.Infof("Shutting down Job Manager") jm.queue.ShutDown() }
// Run begins watching and syncing daemon sets. func (dsc *DaemonSetsController) Run(workers int, stopCh <-chan struct{}) { defer util.HandleCrash() go dsc.dsController.Run(stopCh) go dsc.podController.Run(stopCh) go dsc.nodeController.Run(stopCh) for i := 0; i < workers; i++ { go util.Until(dsc.worker, time.Second, stopCh) } <-stopCh glog.Infof("Shutting down Daemon Set Controller") dsc.queue.ShutDown() }
func newPortRangeAllocator(r util.PortRange) PortAllocator { if r.Base == 0 || r.Size == 0 { panic("illegal argument: may not specify an empty port range") } ra := &rangeAllocator{ PortRange: r, ports: make(chan int, portsBufSize), rand: rand.New(rand.NewSource(time.Now().UnixNano())), } go util.Until(func() { ra.fillPorts(util.NeverStop) }, nextFreePortCooldown, util.NeverStop) return ra }
func TestUpdatePods(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, controller.NoResyncPeriodFunc, BurstReplicas) manager.podStoreSynced = alwaysReady received := make(chan string) manager.syncHandler = func(key string) error { obj, exists, err := manager.rcStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find controller under key %v", key) } received <- obj.(*api.ReplicationController).Name return nil } stopCh := make(chan struct{}) defer close(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) // Put 2 rcs and one pod into the controller's stores testControllerSpec1 := newReplicationController(1) manager.rcStore.Store.Add(testControllerSpec1) testControllerSpec2 := *testControllerSpec1 testControllerSpec2.Spec.Selector = map[string]string{"bar": "foo"} testControllerSpec2.Name = "barfoo" manager.rcStore.Store.Add(&testControllerSpec2) // Put one pod in the podStore pod1 := newPodList(manager.podStore.Store, 1, api.PodRunning, testControllerSpec1).Items[0] pod2 := pod1 pod2.Labels = testControllerSpec2.Spec.Selector // Send an update of the same pod with modified labels, and confirm we get a sync request for // both controllers manager.updatePod(&pod1, &pod2) expected := sets.NewString(testControllerSpec1.Name, testControllerSpec2.Name) for _, name := range expected.List() { t.Logf("Expecting update for %+v", name) select { case got := <-received: if !expected.Has(got) { t.Errorf("Expected keys %#v got %v", expected, got) } case <-time.After(util.ForeverTestTimeout): t.Errorf("Expected update notifications for controllers within 100ms each") } } }
// Runs e; will not return until stopCh is closed. workers determines how many // endpoints will be handled in parallel. func (e *endpointController) Run(workers int, stopCh <-chan struct{}) { defer util.HandleCrash() go e.serviceController.Run(stopCh) go e.podController.Run(stopCh) for i := 0; i < workers; i++ { go util.Until(e.worker, time.Second, stopCh) } go func() { defer util.HandleCrash() time.Sleep(5 * time.Minute) // give time for our cache to fill e.checkLeftoverEndpoints() }() <-stopCh e.queue.ShutDown() }
// Channel returns a channel where a configuration source // can send updates of new configurations. Multiple calls with the same // source will return the same channel. This allows change and state based sources // to use the same channel. Different source names however will be treated as a // union. func (m *Mux) Channel(source string) chan interface{} { if len(source) == 0 { panic("Channel given an empty name") } m.sourceLock.Lock() defer m.sourceLock.Unlock() channel, exists := m.sources[source] if exists { return channel } newChannel := make(chan interface{}) m.sources[source] = newChannel go util.Until(func() { m.listen(source, newChannel) }, 0, util.NeverStop) return newChannel }
// Run begins processing items, and will continue until a value is sent down stopCh. // It's an error to call Run more than once. // Run blocks; call via go. func (c *Controller) Run(stopCh <-chan struct{}) { defer util.HandleCrash() r := cache.NewReflector( c.config.ListerWatcher, c.config.ObjectType, c.config.Queue, c.config.FullResyncPeriod, ) c.reflectorMutex.Lock() c.reflector = r c.reflectorMutex.Unlock() r.RunUntil(stopCh) util.Until(c.processLoop, time.Second, stopCh) }
// runs the main kubelet loop, closing the kubeletFinished chan when the loop exits. // never returns. func (kl *kubeletExecutor) Run(updates <-chan kubelet.PodUpdate) { defer func() { close(kl.kubeletFinished) util.HandleCrash() log.Infoln("kubelet run terminated") //TODO(jdef) turn down verbosity // important: never return! this is in our contract select {} }() // push updates through a closable pipe. when the executor indicates shutdown // via Done() we want to stop the Kubelet from processing updates. pipe := make(chan kubelet.PodUpdate) go func() { // closing pipe will cause our patched kubelet's syncLoop() to exit defer close(pipe) pipeLoop: for { select { case <-kl.executorDone: break pipeLoop default: select { case u := <-updates: select { case pipe <- u: // noop case <-kl.executorDone: break pipeLoop } case <-kl.executorDone: break pipeLoop } } } }() // we expect that Run() will complete after the pipe is closed and the // kubelet's syncLoop() has finished processing its backlog, which hopefully // will not take very long. Peeking into the future (current k8s master) it // seems that the backlog has grown from 1 to 50 -- this may negatively impact // us going forward, time will tell. util.Until(func() { kl.Kubelet.Run(pipe) }, 0, kl.executorDone) //TODO(jdef) revisit this if/when executor failover lands // Force kubelet to delete all pods. kl.HandlePodDeletions(kl.GetPods()) }
func (m *manager) Start() { // Don't start the status manager if we don't have a client. This will happen // on the master, where the kubelet is responsible for bootstrapping the pods // of the master components. if m.kubeClient == nil { glog.Infof("Kubernetes client is nil, not starting status manager.") return } // syncBatch blocks when no updates are available, we can run it in a tight loop. glog.Info("Starting to sync pod status with apiserver") go util.Until(func() { err := m.syncBatch() if err != nil { glog.Warningf("Failed to updated pod status: %v", err) } }, 0, util.NeverStop) }
func (im *realImageManager) Start() error { // Initial detection make detected time "unknown" in the past. var zero time.Time err := im.detectImages(zero) if err != nil { return err } go util.Until(func() { err := im.detectImages(time.Now()) if err != nil { glog.Warningf("[ImageManager] Failed to monitor images: %v", err) } }, 5*time.Minute, util.NeverStop) return nil }
func TestWatchPods(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewJobController(client, controller.NoResyncPeriodFunc) manager.podStoreSynced = alwaysReady // Put one job and one pod into the store testJob := newJob(2, 2) manager.jobStore.Store.Add(testJob) received := make(chan string) // The pod update sent through the fakeWatcher should figure out the managing job and // send it into the syncHandler. manager.syncHandler = func(key string) error { obj, exists, err := manager.jobStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find job under key %v", key) } job := obj.(*extensions.Job) if !api.Semantic.DeepDerivative(job, testJob) { t.Errorf("\nExpected %#v,\nbut got %#v", testJob, job) } close(received) return nil } // Start only the pod watcher and the workqueue, send a watch event, // and make sure it hits the sync method for the right job. stopCh := make(chan struct{}) defer close(stopCh) go manager.podController.Run(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) pods := newPodList(1, api.PodRunning, testJob) testPod := pods[0] testPod.Status.Phase = api.PodFailed fakeWatch.Add(&testPod) select { case <-received: case <-time.After(controllerTimeout): t.Errorf("Expected 1 call but got 0") } }
func TestWatchControllers(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, controller.NoResyncPeriodFunc, BurstReplicas) manager.podStoreSynced = alwaysReady var testControllerSpec api.ReplicationController received := make(chan string) // The update sent through the fakeWatcher should make its way into the workqueue, // and eventually into the syncHandler. The handler validates the received controller // and closes the received channel to indicate that the test can finish. manager.syncHandler = func(key string) error { obj, exists, err := manager.rcStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find controller under key %v", key) } controllerSpec := *obj.(*api.ReplicationController) if !api.Semantic.DeepDerivative(controllerSpec, testControllerSpec) { t.Errorf("Expected %#v, but got %#v", testControllerSpec, controllerSpec) } close(received) return nil } // Start only the rc watcher and the workqueue, send a watch event, // and make sure it hits the sync method. stopCh := make(chan struct{}) defer close(stopCh) go manager.rcController.Run(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) testControllerSpec.Name = "foo" fakeWatch.Add(&testControllerSpec) select { case <-received: case <-time.After(util.ForeverTestTimeout): t.Errorf("Expected 1 call but got 0") } }
func testMasterUpgrade(ip, v string, mUp func(v string) error) { Logf("Starting async validation") httpClient := http.Client{Timeout: 2 * time.Second} done := make(chan struct{}, 1) // Let's make sure we've finished the heartbeat before shutting things down. var wg sync.WaitGroup go util.Until(func() { defer GinkgoRecover() wg.Add(1) defer wg.Done() if err := wait.Poll(poll, singleCallTimeout, func() (bool, error) { r, err := httpClient.Get("http://" + ip) if err != nil { Logf("Error reaching %s: %v", ip, err) return false, nil } if r.StatusCode < http.StatusOK || r.StatusCode >= http.StatusNotFound { Logf("Bad response; status: %d, response: %v", r.StatusCode, r) return false, nil } return true, nil }); err != nil { // We log the error here because the test will fail at the very end // because this validation runs in another goroutine. Without this, // a failure is very confusing to track down because from the logs // everything looks fine. msg := fmt.Sprintf("Failed to contact service during master upgrade: %v", err) Logf(msg) Failf(msg) } }, 200*time.Millisecond, done) Logf("Starting master upgrade") expectNoError(mUp(v)) done <- struct{}{} Logf("Stopping async validation") wg.Wait() Logf("Master upgrade complete") }
// Create a new Cacher responsible from service WATCH and LIST requests from its // internal cache and updating its cache in the background based on the given // configuration. func NewCacher(config CacherConfig) *Cacher { watchCache := newWatchCache(config.CacheCapacity) listerWatcher := newCacherListerWatcher(config.Storage, config.ResourcePrefix, config.NewListFunc) cacher := &Cacher{ usable: sync.RWMutex{}, storage: config.Storage, watchCache: watchCache, reflector: cache.NewReflector(listerWatcher, config.Type, watchCache, 0), watcherIdx: 0, watchers: make(map[int]*cacheWatcher), versioner: config.Versioner, keyFunc: config.KeyFunc, } cacher.usable.Lock() // See startCaching method for why explanation on it. watchCache.SetOnReplace(func() { cacher.usable.Unlock() }) watchCache.SetOnEvent(cacher.processEvent) stopCh := config.StopChannel go util.Until(func() { cacher.startCaching(stopCh) }, 0, stopCh) return cacher }
// Elect implements the election.MasterElector interface. func (e *etcdMasterElector) Elect(path, id string) watch.Interface { e.done = make(chan empty) e.events = make(chan watch.Event) go util.Until(func() { e.run(path, id) }, time.Second*5, util.NeverStop) return e }
func (gcc *GCController) Run(stop <-chan struct{}) { go gcc.podStoreSyncer.Run(stop) go util.Until(gcc.gc, gcCheckPeriod, stop) <-stop }