Change:
Please see : https://k8s- fails just after this line: Failure was introduced in: But this was not noticed until it started running in [Conformance] tests. You can see the same problem in other dashboards too: https://k8s- https://k8s-
cc /sig apps
/priority critical-urgent
/kind bug /priority failing-test
/milestone v1.10
Is this just an oversight of not removing the template generation when the API update was done?
/cc
triaged in progress
i have never touched this test before ... so i just threw in a WIP, feel free to use/discard it. there seems to be lot of methods in there that is no longer used, may be we can rip those out too. (see )
xref
[MILESTONENOTIFIER] Milestone Issue Needs Attention Action Required: This issue has not been updated since Mar 5. Please provide an update. Note: This issue is marked as , and must be updated every 1 day during code freeze. Example update: <details<summaryIssue Labels</summary- : Issue will be escalated to these SIGs if needed. : Never automatically move issue out of a release milestone; continually escalate to contributor and SIG through all available channels. : Fixes a bug discovered during the current release. </details<details<summaryHelp</summary<ul<li<a href=""Additional instructions</a</li<li<a href=""Commands for setting labels</a</li</ul</details

Discussion:
"//pkg/apis/core:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", <del> "//pkg/controller:go_default_library", </del> "//pkg/controller/daemon:go_default_library", "//pkg/controller/deployment/util:go_default_library", "//pkg/controller/job:go_default_library",

"k8s.io/kubernetes/pkg/api/legacyscheme" podutil "k8s.io/kubernetes/pkg/api/v1/pod" extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" <del> "k8s.io/kubernetes/pkg/controller" </del> "k8s.io/kubernetes/pkg/controller/daemon" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/scheduler/schedulercache"

framework.ConformanceIt("should update pod when spec was updated and update strategy is RollingUpdate", func() { label := map[string]string{daemonsetNameLabel: dsName} <del> templateGeneration := int64(999) framework.Logf("Creating simple daemon set %s with templateGeneration %d", dsName, templateGeneration) </del> <ins> framework.Logf("Creating simple daemon set %s", dsName) </ins> ds := newDaemonSet(dsName, image, label) ds.Spec.UpdateStrategy = apps.DaemonSetUpdateStrategy{Type: apps.RollingUpdateDaemonSetStrategyType} ds, err := c.AppsV1().DaemonSets(ns).Create(ds)

err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, ds)) Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start") <del> By(fmt.Sprintf("Make sure all daemon pods have correct template generation %d", templateGeneration)) err = checkDaemonPodsTemplateGeneration(c, ns, label, fmt.Sprint(templateGeneration)) Expect(err).NotTo(HaveOccurred()) </del> // Check history and labels ds, err = c.AppsV1().DaemonSets(ns).Get(ds.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred())

patch := getDaemonSetImagePatch(ds.Spec.Template.Spec.Containers[0].Name, RedisImage) ds, err = c.AppsV1().DaemonSets(ns).Patch(dsName, types.StrategicMergePatchType, []byte(patch)) Expect(err).NotTo(HaveOccurred()) <del> templateGeneration++ </del> By("Check that daemon pods images are updated.") err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonPodsImageAndAvailability(c, ds, RedisImage, 1)) Expect(err).NotTo(HaveOccurred()) <del> By(fmt.Sprintf("Make sure all daemon pods have correct template generation %d", templateGeneration)) err = checkDaemonPodsTemplateGeneration(c, ns, label, fmt.Sprint(templateGeneration)) Expect(err).NotTo(HaveOccurred()) </del> By("Check that daemon pods are still running on every node of the cluster.") err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkRunningOnAllNodes(f, ds)) Expect(err).NotTo(HaveOccurred(), "error waiting for daemon pod to start")

return fmt.Sprintf(`{"spec":{"template":{"spec":{"containers":[{"name":"%s","image":"%s"}]}}}}`, containerName, containerImage) } <del> // deleteDaemonSetAndOrphan deletes the given DaemonSet and orphans all its dependents. // It also checks that all dependents are orphaned, and the DaemonSet is deleted. func deleteDaemonSetAndOrphan(c clientset.Interface, ds *apps.DaemonSet) { trueVar := true deleteOptions := &metav1.DeleteOptions{OrphanDependents: &trueVar} deleteOptions.Preconditions = metav1.NewUIDPreconditions(string(ds.UID)) err := c.AppsV1().DaemonSets(ds.Namespace).Delete(ds.Name, deleteOptions) Expect(err).NotTo(HaveOccurred()) err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonSetPodsOrphaned(c, ds.Namespace, ds.Spec.Template.Labels)) Expect(err).NotTo(HaveOccurred(), "error waiting for DaemonSet pods to be orphaned") err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonSetHistoryOrphaned(c, ds.Namespace, ds.Spec.Template.Labels)) Expect(err).NotTo(HaveOccurred(), "error waiting for DaemonSet history to be orphaned") err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonSetDeleted(c, ds.Namespace, ds.Name)) Expect(err).NotTo(HaveOccurred(), "error waiting for DaemonSet to be deleted") } </del> func newDaemonSet(dsName, image string, label map[string]string) *apps.DaemonSet { return &apps.DaemonSet{ ObjectMeta: metav1.ObjectMeta{

} } <del> func checkDaemonPodsTemplateGeneration(c clientset.Interface, ns string, label map[string]string, templateGeneration string) error { pods := listDaemonPods(c, ns, label) for _, pod := range pods.Items { // We don't care about inactive pods if !controller.IsPodActive(&pod) { continue } podTemplateGeneration := pod.Labels[apps.DeprecatedTemplateGeneration] if podTemplateGeneration != templateGeneration { return fmt.Errorf("expected pod %s/%s template generation %s, but got %s", pod.Namespace, pod.Name, templateGeneration, podTemplateGeneration) } } return nil } func checkDaemonSetDeleted(c clientset.Interface, ns, name string) func() (bool, error) { return func() (bool, error) { _, err := c.AppsV1().DaemonSets(ns).Get(name, metav1.GetOptions{}) if !apierrs.IsNotFound(err) { return false, err } return true, nil } } func checkDaemonSetPodsOrphaned(c clientset.Interface, ns string, label map[string]string) func() (bool, error) { return func() (bool, error) { pods := listDaemonPods(c, ns, label) for _, pod := range pods.Items { // This pod is orphaned only when controller ref is cleared if controllerRef := metav1.GetControllerOf(&pod); controllerRef != nil { return false, nil } } return true, nil } } func checkDaemonSetHistoryOrphaned(c clientset.Interface, ns string, label map[string]string) func() (bool, error) { return func() (bool, error) { histories := listDaemonHistories(c, ns, label) for _, history := range histories.Items { // This history is orphaned only when controller ref is cleared if controllerRef := metav1.GetControllerOf(&history); controllerRef != nil { return false, nil } } return true, nil } } func checkDaemonSetPodsAdopted(c clientset.Interface, ns string, dsUID types.UID, label map[string]string) func() (bool, error) { return func() (bool, error) { pods := listDaemonPods(c, ns, label) for _, pod := range pods.Items { // This pod is adopted only when its controller ref is update if controllerRef := metav1.GetControllerOf(&pod); controllerRef == nil || controllerRef.UID != dsUID { return false, nil } } return true, nil } } func checkDaemonSetHistoryAdopted(c clientset.Interface, ns string, dsUID types.UID, label map[string]string) func() (bool, error) { return func() (bool, error) { histories := listDaemonHistories(c, ns, label) for _, history := range histories.Items { // This history is adopted only when its controller ref is update if controllerRef := metav1.GetControllerOf(&history); controllerRef == nil || controllerRef.UID != dsUID { return false, nil } } return true, nil } } func waitDaemonSetAdoption(c clientset.Interface, ds *apps.DaemonSet, podPrefix string, podTemplateGeneration int64) { ns := ds.Namespace label := ds.Spec.Template.Labels err := wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonSetPodsAdopted(c, ns, ds.UID, label)) Expect(err).NotTo(HaveOccurred(), "error waiting for DaemonSet pods to be adopted") err = wait.PollImmediate(dsRetryPeriod, dsRetryTimeout, checkDaemonSetHistoryAdopted(c, ns, ds.UID, label)) Expect(err).NotTo(HaveOccurred(), "error waiting for DaemonSet history to be adopted") framework.Logf("Make sure no daemon pod updated its template generation %d", podTemplateGeneration) err = checkDaemonPodsTemplateGeneration(c, ns, label, fmt.Sprint(podTemplateGeneration)) Expect(err).NotTo(HaveOccurred()) framework.Logf("Make sure no pods are recreated by looking at their names") err = checkDaemonSetPodsName(c, ns, podPrefix, label) Expect(err).NotTo(HaveOccurred()) } func checkDaemonSetPodsName(c clientset.Interface, ns, prefix string, label map[string]string) error { pods := listDaemonPods(c, ns, label) for _, pod := range pods.Items { if !strings.HasPrefix(pod.Name, prefix) { return fmt.Errorf("expected pod %s name to be prefixed %q", pod.Name, prefix) } } return nil } </del> func checkDaemonSetPodsLabels(podList *v1.PodList, hash string) { for _, pod := range podList.Items { podHash := pod.Labels[apps.DefaultDaemonSetUniqueLabelKey]