// Stop attempts to gracefully stop `kubectl port-forward`, only killing it if necessary. // This helps avoid spdy goroutine leaks in the Kubelet. func (c *portForwardCommand) Stop() { // SIGINT signals that kubectl port-forward should gracefully terminate if err := c.cmd.Process.Signal(syscall.SIGINT); err != nil { framework.Logf("error sending SIGINT to kubectl port-forward: %v", err) } // try to wait for a clean exit done := make(chan error) go func() { done <- c.cmd.Wait() }() expired := time.NewTimer(wait.ForeverTestTimeout) defer expired.Stop() select { case err := <-done: if err == nil { // success return } framework.Logf("error waiting for kubectl port-forward to exit: %v", err) case <-expired.C: framework.Logf("timed out waiting for kubectl port-forward to exit") } framework.Logf("trying to forcibly kill kubectl port-forward") framework.TryKill(c.cmd) }
} // We need to wait for the pod to be running, otherwise the deletion // may be carried out immediately rather than gracefully. framework.ExpectNoError(f.WaitForPodRunning(pod.Name)) // save the running pod pod, err = podClient.Get(pod.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred(), "failed to GET scheduled pod") // start local proxy, so we can send graceful deletion over query string, rather than body parameter cmd := framework.KubectlCmd("proxy", "-p", "0") stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd) Expect(err).NotTo(HaveOccurred(), "failed to start up proxy") defer stdout.Close() defer stderr.Close() defer framework.TryKill(cmd) buf := make([]byte, 128) var n int n, err = stdout.Read(buf) Expect(err).NotTo(HaveOccurred(), "failed to read from kubectl proxy stdout") output := string(buf[:n]) proxyRegexp := regexp.MustCompile("Starting to serve on 127.0.0.1:([0-9]+)") match := proxyRegexp.FindStringSubmatch(output) Expect(len(match)).To(Equal(2)) port, err := strconv.Atoi(match[1]) Expect(err).NotTo(HaveOccurred(), "failed to convert port into string") endpoint := fmt.Sprintf("http://localhost:%d/api/v1/namespaces/%s/pods/%s?gracePeriodSeconds=30", port, pod.Namespace, pod.Name) tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }