// syncPod syncs the given status with the API server. The caller must not hold the lock. func (m *manager) syncPod(uid types.UID, status versionedPodStatus) { if !m.needsUpdate(uid, status) { glog.V(1).Infof("Status for pod %q is up-to-date; skipping", uid) return } // TODO: make me easier to express from client code pod, err := m.kubeClient.Core().Pods(status.podNamespace).Get(status.podName, metav1.GetOptions{}) if errors.IsNotFound(err) { glog.V(3).Infof("Pod %q (%s) does not exist on the server", status.podName, uid) // If the Pod is deleted the status will be cleared in // RemoveOrphanedStatuses, so we just ignore the update here. return } if err == nil { translatedUID := m.podManager.TranslatePodUID(pod.UID) if len(translatedUID) > 0 && translatedUID != uid { glog.V(2).Infof("Pod %q was deleted and then recreated, skipping status update; old UID %q, new UID %q", format.Pod(pod), uid, translatedUID) m.deletePodStatus(uid) return } pod.Status = status.status if err := podutil.SetInitContainersStatusesAnnotations(pod); err != nil { glog.Error(err) } // TODO: handle conflict as a retry, make that easier too. pod, err = m.kubeClient.Core().Pods(pod.Namespace).UpdateStatus(pod) if err == nil { glog.V(3).Infof("Status for pod %q updated successfully: %+v", format.Pod(pod), status) m.apiStatusVersions[pod.UID] = status.version if kubepod.IsMirrorPod(pod) { // We don't handle graceful deletion of mirror pods. return } if pod.DeletionTimestamp == nil { return } if !notRunning(pod.Status.ContainerStatuses) { glog.V(3).Infof("Pod %q is terminated, but some containers are still running", format.Pod(pod)) return } deleteOptions := v1.NewDeleteOptions(0) // Use the pod UID as the precondition for deletion to prevent deleting a newly created pod with the same name and namespace. deleteOptions.Preconditions = v1.NewUIDPreconditions(string(pod.UID)) if err = m.kubeClient.Core().Pods(pod.Namespace).Delete(pod.Name, deleteOptions); err == nil { glog.V(3).Infof("Pod %q fully terminated and removed from etcd", format.Pod(pod)) m.deletePodStatus(uid) return } } } // We failed to update status, wait for periodic sync to retry. glog.Warningf("Failed to update status for pod %q: %v", format.Pod(pod), err) }
} // We intentionally don't wait the number of pods to reach // rc.Spec.Replicas. We want to see if the garbage collector and the // rc manager work properly if the rc is deleted before it reaches // stasis. if len(pods.Items) > 0 { return true, nil } else { return false, nil } }); err != nil { framework.Failf("failed to wait for the rc to create some pods: %v", err) } By("delete the rc") deleteOptions := getNonOrphanOptions() deleteOptions.Preconditions = v1.NewUIDPreconditions(string(rc.UID)) if err := rcClient.Delete(rc.ObjectMeta.Name, deleteOptions); err != nil { framework.Failf("failed to delete the rc: %v", err) } By("wait for all pods to be garbage collected") // wait for the RCs and Pods to reach the expected numbers. if err := wait.Poll(5*time.Second, 60*time.Second, func() (bool, error) { return verifyRemainingObjects(f, clientSet, 0, 0) }); err != nil { framework.Failf("failed to wait for all pods to be deleted: %v", err) remainingPods, err := podClient.List(v1.ListOptions{}) if err != nil { framework.Failf("failed to list pods post mortem: %v", err) } else { framework.Failf("remaining pods are: %#v", remainingPods) }