...

Source file src/k8s.io/kubernetes/test/integration/replicaset/replicaset_test.go

Documentation: k8s.io/kubernetes/test/integration/replicaset

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package replicaset
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"reflect"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	apps "k8s.io/api/apps/v1"
    28  	v1 "k8s.io/api/core/v1"
    29  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/labels"
    32  	"k8s.io/apimachinery/pkg/util/uuid"
    33  	"k8s.io/apimachinery/pkg/util/wait"
    34  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    35  	"k8s.io/client-go/informers"
    36  	clientset "k8s.io/client-go/kubernetes"
    37  	appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
    38  	typedv1 "k8s.io/client-go/kubernetes/typed/core/v1"
    39  	restclient "k8s.io/client-go/rest"
    40  	"k8s.io/client-go/tools/cache"
    41  	"k8s.io/client-go/util/retry"
    42  	featuregatetesting "k8s.io/component-base/featuregate/testing"
    43  	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
    44  	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
    45  	"k8s.io/kubernetes/pkg/apis/core"
    46  	"k8s.io/kubernetes/pkg/controller/replicaset"
    47  	"k8s.io/kubernetes/pkg/features"
    48  	"k8s.io/kubernetes/test/integration/framework"
    49  	testutil "k8s.io/kubernetes/test/utils"
    50  	"k8s.io/kubernetes/test/utils/ktesting"
    51  	"k8s.io/utils/ptr"
    52  )
    53  
    54  const (
    55  	interval = 100 * time.Millisecond
    56  	timeout  = 60 * time.Second
    57  )
    58  
    59  func labelMap() map[string]string {
    60  	return map[string]string{"foo": "bar"}
    61  }
    62  
    63  func newRS(name, namespace string, replicas int) *apps.ReplicaSet {
    64  	replicasCopy := int32(replicas)
    65  	return &apps.ReplicaSet{
    66  		TypeMeta: metav1.TypeMeta{
    67  			Kind:       "ReplicaSet",
    68  			APIVersion: "apps/v1",
    69  		},
    70  		ObjectMeta: metav1.ObjectMeta{
    71  			Namespace: namespace,
    72  			Name:      name,
    73  		},
    74  		Spec: apps.ReplicaSetSpec{
    75  			Selector: &metav1.LabelSelector{
    76  				MatchLabels: labelMap(),
    77  			},
    78  			Replicas: &replicasCopy,
    79  			Template: v1.PodTemplateSpec{
    80  				ObjectMeta: metav1.ObjectMeta{
    81  					Labels: labelMap(),
    82  				},
    83  				Spec: v1.PodSpec{
    84  					Containers: []v1.Container{
    85  						{
    86  							Name:  "fake-name",
    87  							Image: "fakeimage",
    88  						},
    89  					},
    90  				},
    91  			},
    92  		},
    93  	}
    94  }
    95  
    96  func newMatchingPod(podName, namespace string) *v1.Pod {
    97  	return &v1.Pod{
    98  		TypeMeta: metav1.TypeMeta{
    99  			Kind:       "Pod",
   100  			APIVersion: "v1",
   101  		},
   102  		ObjectMeta: metav1.ObjectMeta{
   103  			Name:      podName,
   104  			Namespace: namespace,
   105  			Labels:    labelMap(),
   106  		},
   107  		Spec: v1.PodSpec{
   108  			Containers: []v1.Container{
   109  				{
   110  					Name:  "fake-name",
   111  					Image: "fakeimage",
   112  				},
   113  			},
   114  		},
   115  		Status: v1.PodStatus{
   116  			Phase: v1.PodRunning,
   117  		},
   118  	}
   119  }
   120  
   121  func rmSetup(t *testing.T) (context.Context, kubeapiservertesting.TearDownFunc, *replicaset.ReplicaSetController, informers.SharedInformerFactory, clientset.Interface) {
   122  	tCtx := ktesting.Init(t)
   123  	// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
   124  	server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd())
   125  
   126  	config := restclient.CopyConfig(server.ClientConfig)
   127  	clientSet, err := clientset.NewForConfig(config)
   128  	if err != nil {
   129  		t.Fatalf("Error in create clientset: %v", err)
   130  	}
   131  	resyncPeriod := 12 * time.Hour
   132  	informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(config, "rs-informers")), resyncPeriod)
   133  
   134  	rm := replicaset.NewReplicaSetController(
   135  		tCtx,
   136  		informers.Apps().V1().ReplicaSets(),
   137  		informers.Core().V1().Pods(),
   138  		clientset.NewForConfigOrDie(restclient.AddUserAgent(config, "replicaset-controller")),
   139  		replicaset.BurstReplicas,
   140  	)
   141  
   142  	newTeardown := func() {
   143  		tCtx.Cancel("tearing down controller")
   144  		server.TearDownFn()
   145  	}
   146  
   147  	return tCtx, newTeardown, rm, informers, clientSet
   148  }
   149  
   150  func rmSimpleSetup(t *testing.T) (kubeapiservertesting.TearDownFunc, clientset.Interface) {
   151  	// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
   152  	server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd())
   153  
   154  	config := restclient.CopyConfig(server.ClientConfig)
   155  	clientSet, err := clientset.NewForConfig(config)
   156  	if err != nil {
   157  		t.Fatalf("Error in create clientset: %v", err)
   158  	}
   159  	return server.TearDownFn, clientSet
   160  }
   161  
   162  // Run RS controller and informers
   163  func runControllerAndInformers(t *testing.T, rm *replicaset.ReplicaSetController, informers informers.SharedInformerFactory, podNum int) func() {
   164  	ctx, cancelFn := context.WithCancel(context.Background())
   165  	informers.Start(ctx.Done())
   166  	waitToObservePods(t, informers.Core().V1().Pods().Informer(), podNum)
   167  	go rm.Run(ctx, 5)
   168  	return cancelFn
   169  }
   170  
   171  // wait for the podInformer to observe the pods. Call this function before
   172  // running the RS controller to prevent the rc manager from creating new pods
   173  // rather than adopting the existing ones.
   174  func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podNum int) {
   175  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   176  		objects := podInformer.GetIndexer().List()
   177  		return len(objects) == podNum, nil
   178  	}); err != nil {
   179  		t.Fatalf("Error encountered when waiting for podInformer to observe the pods: %v", err)
   180  	}
   181  }
   182  
   183  func createRSsPods(t *testing.T, clientSet clientset.Interface, rss []*apps.ReplicaSet, pods []*v1.Pod) ([]*apps.ReplicaSet, []*v1.Pod) {
   184  	var createdRSs []*apps.ReplicaSet
   185  	var createdPods []*v1.Pod
   186  	for _, rs := range rss {
   187  		createdRS, err := clientSet.AppsV1().ReplicaSets(rs.Namespace).Create(context.TODO(), rs, metav1.CreateOptions{})
   188  		if err != nil {
   189  			t.Fatalf("Failed to create replica set %s: %v", rs.Name, err)
   190  		}
   191  		createdRSs = append(createdRSs, createdRS)
   192  	}
   193  	for _, pod := range pods {
   194  		createdPod, err := clientSet.CoreV1().Pods(pod.Namespace).Create(context.TODO(), pod, metav1.CreateOptions{})
   195  		if err != nil {
   196  			t.Fatalf("Failed to create pod %s: %v", pod.Name, err)
   197  		}
   198  		createdPods = append(createdPods, createdPod)
   199  	}
   200  
   201  	return createdRSs, createdPods
   202  }
   203  
   204  // Verify .Status.Replicas is equal to .Spec.Replicas
   205  func waitRSStable(t *testing.T, clientSet clientset.Interface, rs *apps.ReplicaSet) {
   206  	if err := testutil.WaitRSStable(t, clientSet, rs, interval, timeout); err != nil {
   207  		t.Fatal(err)
   208  	}
   209  }
   210  
   211  // Update .Spec.Replicas to replicas and verify .Status.Replicas is changed accordingly
   212  func scaleRS(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) {
   213  	rsClient := c.AppsV1().ReplicaSets(rs.Namespace)
   214  	rs = updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
   215  		*rs.Spec.Replicas = replicas
   216  	})
   217  	waitRSStable(t, c, rs)
   218  }
   219  
   220  func updatePod(t *testing.T, podClient typedv1.PodInterface, podName string, updateFunc func(*v1.Pod)) *v1.Pod {
   221  	var pod *v1.Pod
   222  	if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
   223  		newPod, err := podClient.Get(context.TODO(), podName, metav1.GetOptions{})
   224  		if err != nil {
   225  			return err
   226  		}
   227  		updateFunc(newPod)
   228  		pod, err = podClient.Update(context.TODO(), newPod, metav1.UpdateOptions{})
   229  		return err
   230  	}); err != nil {
   231  		t.Fatalf("Failed to update pod %s: %v", podName, err)
   232  	}
   233  	return pod
   234  }
   235  
   236  func updatePodStatus(t *testing.T, podClient typedv1.PodInterface, podName string, updateStatusFunc func(*v1.Pod)) {
   237  	if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
   238  		newPod, err := podClient.Get(context.TODO(), podName, metav1.GetOptions{})
   239  		if err != nil {
   240  			return err
   241  		}
   242  		updateStatusFunc(newPod)
   243  		_, err = podClient.UpdateStatus(context.TODO(), newPod, metav1.UpdateOptions{})
   244  		return err
   245  	}); err != nil {
   246  		t.Fatalf("Failed to update status of pod %s: %v", podName, err)
   247  	}
   248  }
   249  
   250  func getPods(t *testing.T, podClient typedv1.PodInterface, labelMap map[string]string) *v1.PodList {
   251  	podSelector := labels.Set(labelMap).AsSelector()
   252  	options := metav1.ListOptions{LabelSelector: podSelector.String()}
   253  	pods, err := podClient.List(context.TODO(), options)
   254  	if err != nil {
   255  		t.Fatalf("Failed obtaining a list of pods that match the pod labels %v: %v", labelMap, err)
   256  	}
   257  	return pods
   258  }
   259  
   260  func updateRS(t *testing.T, rsClient appsclient.ReplicaSetInterface, rsName string, updateFunc func(*apps.ReplicaSet)) *apps.ReplicaSet {
   261  	var rs *apps.ReplicaSet
   262  	if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
   263  		newRS, err := rsClient.Get(context.TODO(), rsName, metav1.GetOptions{})
   264  		if err != nil {
   265  			return err
   266  		}
   267  		updateFunc(newRS)
   268  		rs, err = rsClient.Update(context.TODO(), newRS, metav1.UpdateOptions{})
   269  		return err
   270  	}); err != nil {
   271  		t.Fatalf("Failed to update rs %s: %v", rsName, err)
   272  	}
   273  	return rs
   274  }
   275  
   276  // Verify ControllerRef of a RS pod that has incorrect attributes is automatically patched by the RS
   277  func testPodControllerRefPatch(t *testing.T, c clientset.Interface, pod *v1.Pod, ownerReference *metav1.OwnerReference, rs *apps.ReplicaSet, expectedOwnerReferenceNum int) {
   278  	ns := rs.Namespace
   279  	podClient := c.CoreV1().Pods(ns)
   280  	updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
   281  		pod.OwnerReferences = []metav1.OwnerReference{*ownerReference}
   282  	})
   283  
   284  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   285  		newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
   286  		if err != nil {
   287  			return false, err
   288  		}
   289  		return metav1.GetControllerOf(newPod) != nil, nil
   290  	}); err != nil {
   291  		t.Fatalf("Failed to verify ControllerRef for the pod %s is not nil: %v", pod.Name, err)
   292  	}
   293  
   294  	newPod, err := podClient.Get(context.TODO(), pod.Name, metav1.GetOptions{})
   295  	if err != nil {
   296  		t.Fatalf("Failed to obtain pod %s: %v", pod.Name, err)
   297  	}
   298  	controllerRef := metav1.GetControllerOf(newPod)
   299  	if controllerRef.UID != rs.UID {
   300  		t.Fatalf("RS owner of the pod %s has a different UID: Expected %v, got %v", newPod.Name, rs.UID, controllerRef.UID)
   301  	}
   302  	ownerReferenceNum := len(newPod.GetOwnerReferences())
   303  	if ownerReferenceNum != expectedOwnerReferenceNum {
   304  		t.Fatalf("Unexpected number of owner references for pod %s: Expected %d, got %d", newPod.Name, expectedOwnerReferenceNum, ownerReferenceNum)
   305  	}
   306  }
   307  
   308  func setPodsReadyCondition(t *testing.T, clientSet clientset.Interface, pods *v1.PodList, conditionStatus v1.ConditionStatus, lastTransitionTime time.Time) {
   309  	replicas := int32(len(pods.Items))
   310  	var readyPods int32
   311  	err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   312  		readyPods = 0
   313  		for i := range pods.Items {
   314  			pod := &pods.Items[i]
   315  			if podutil.IsPodReady(pod) {
   316  				readyPods++
   317  				continue
   318  			}
   319  			pod.Status.Phase = v1.PodRunning
   320  			_, condition := podutil.GetPodCondition(&pod.Status, v1.PodReady)
   321  			if condition != nil {
   322  				condition.Status = conditionStatus
   323  				condition.LastTransitionTime = metav1.Time{Time: lastTransitionTime}
   324  			} else {
   325  				condition = &v1.PodCondition{
   326  					Type:               v1.PodReady,
   327  					Status:             conditionStatus,
   328  					LastTransitionTime: metav1.Time{Time: lastTransitionTime},
   329  				}
   330  				pod.Status.Conditions = append(pod.Status.Conditions, *condition)
   331  			}
   332  			_, err := clientSet.CoreV1().Pods(pod.Namespace).UpdateStatus(context.TODO(), pod, metav1.UpdateOptions{})
   333  			if err != nil {
   334  				// When status fails to be updated, we continue to next pod
   335  				continue
   336  			}
   337  			readyPods++
   338  		}
   339  		return readyPods >= replicas, nil
   340  	})
   341  	if err != nil {
   342  		t.Fatalf("failed to mark all ReplicaSet pods to ready: %v", err)
   343  	}
   344  }
   345  
   346  func testScalingUsingScaleSubresource(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) {
   347  	ns := rs.Namespace
   348  	rsClient := c.AppsV1().ReplicaSets(ns)
   349  	newRS, err := rsClient.Get(context.TODO(), rs.Name, metav1.GetOptions{})
   350  	if err != nil {
   351  		t.Fatalf("Failed to obtain rs %s: %v", rs.Name, err)
   352  	}
   353  	scale, err := c.AppsV1().ReplicaSets(ns).GetScale(context.TODO(), rs.Name, metav1.GetOptions{})
   354  	if err != nil {
   355  		t.Fatalf("Failed to obtain scale subresource for rs %s: %v", rs.Name, err)
   356  	}
   357  	if scale.Spec.Replicas != *newRS.Spec.Replicas {
   358  		t.Fatalf("Scale subresource for rs %s does not match .Spec.Replicas: expected %d, got %d", rs.Name, *newRS.Spec.Replicas, scale.Spec.Replicas)
   359  	}
   360  
   361  	if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
   362  		scale, err := c.AppsV1().ReplicaSets(ns).GetScale(context.TODO(), rs.Name, metav1.GetOptions{})
   363  		if err != nil {
   364  			return err
   365  		}
   366  		scale.Spec.Replicas = replicas
   367  		_, err = c.AppsV1().ReplicaSets(ns).UpdateScale(context.TODO(), rs.Name, scale, metav1.UpdateOptions{})
   368  		return err
   369  	}); err != nil {
   370  		t.Fatalf("Failed to set .Spec.Replicas of scale subresource for rs %s: %v", rs.Name, err)
   371  	}
   372  
   373  	newRS, err = rsClient.Get(context.TODO(), rs.Name, metav1.GetOptions{})
   374  	if err != nil {
   375  		t.Fatalf("Failed to obtain rs %s: %v", rs.Name, err)
   376  	}
   377  	if *newRS.Spec.Replicas != replicas {
   378  		t.Fatalf(".Spec.Replicas of rs %s does not match its scale subresource: expected %d, got %d", rs.Name, replicas, *newRS.Spec.Replicas)
   379  	}
   380  }
   381  
   382  func TestAdoption(t *testing.T) {
   383  	boolPtr := func(b bool) *bool { return &b }
   384  	testCases := []struct {
   385  		name                    string
   386  		existingOwnerReferences func(rs *apps.ReplicaSet) []metav1.OwnerReference
   387  		expectedOwnerReferences func(rs *apps.ReplicaSet) []metav1.OwnerReference
   388  	}{
   389  		{
   390  			"pod refers rs as an owner, not a controller",
   391  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   392  				return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"}}
   393  			},
   394  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   395  				return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}}
   396  			},
   397  		},
   398  		{
   399  			"pod doesn't have owner references",
   400  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   401  				return []metav1.OwnerReference{}
   402  			},
   403  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   404  				return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true), BlockOwnerDeletion: boolPtr(true)}}
   405  			},
   406  		},
   407  		{
   408  			"pod refers rs as a controller",
   409  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   410  				return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}}
   411  			},
   412  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   413  				return []metav1.OwnerReference{{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)}}
   414  			},
   415  		},
   416  		{
   417  			"pod refers other rs as the controller, refers the rs as an owner",
   418  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   419  				return []metav1.OwnerReference{
   420  					{UID: "1", Name: "anotherRS", APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)},
   421  					{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"},
   422  				}
   423  			},
   424  			func(rs *apps.ReplicaSet) []metav1.OwnerReference {
   425  				return []metav1.OwnerReference{
   426  					{UID: "1", Name: "anotherRS", APIVersion: "apps/v1", Kind: "ReplicaSet", Controller: boolPtr(true)},
   427  					{UID: rs.UID, Name: rs.Name, APIVersion: "apps/v1", Kind: "ReplicaSet"},
   428  				}
   429  			},
   430  		},
   431  	}
   432  	for i, tc := range testCases {
   433  		t.Run(tc.name, func(t *testing.T) {
   434  			tCtx, closeFn, rm, informers, clientSet := rmSetup(t)
   435  			defer closeFn()
   436  
   437  			ns := framework.CreateNamespaceOrDie(clientSet, fmt.Sprintf("rs-adoption-%d", i), t)
   438  			defer framework.DeleteNamespaceOrDie(clientSet, ns, t)
   439  
   440  			rsClient := clientSet.AppsV1().ReplicaSets(ns.Name)
   441  			podClient := clientSet.CoreV1().Pods(ns.Name)
   442  			const rsName = "rs"
   443  			rs, err := rsClient.Create(tCtx, newRS(rsName, ns.Name, 1), metav1.CreateOptions{})
   444  			if err != nil {
   445  				t.Fatalf("Failed to create replica set: %v", err)
   446  			}
   447  			podName := fmt.Sprintf("pod%d", i)
   448  			pod := newMatchingPod(podName, ns.Name)
   449  			pod.OwnerReferences = tc.existingOwnerReferences(rs)
   450  			_, err = podClient.Create(tCtx, pod, metav1.CreateOptions{})
   451  			if err != nil {
   452  				t.Fatalf("Failed to create Pod: %v", err)
   453  			}
   454  
   455  			stopControllers := runControllerAndInformers(t, rm, informers, 1)
   456  			defer stopControllers()
   457  			if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   458  				updatedPod, err := podClient.Get(tCtx, pod.Name, metav1.GetOptions{})
   459  				if err != nil {
   460  					return false, err
   461  				}
   462  
   463  				e, a := tc.expectedOwnerReferences(rs), updatedPod.OwnerReferences
   464  				if reflect.DeepEqual(e, a) {
   465  					return true, nil
   466  				}
   467  
   468  				t.Logf("ownerReferences don't match, expect %v, got %v", e, a)
   469  				return false, nil
   470  			}); err != nil {
   471  				t.Fatalf("test %q failed: %v", tc.name, err)
   472  			}
   473  		})
   474  	}
   475  }
   476  
   477  // selectors are IMMUTABLE for all API versions except extensions/v1beta1
   478  func TestRSSelectorImmutability(t *testing.T) {
   479  	closeFn, clientSet := rmSimpleSetup(t)
   480  	defer closeFn()
   481  	ns := framework.CreateNamespaceOrDie(clientSet, "rs-selector-immutability", t)
   482  	defer framework.DeleteNamespaceOrDie(clientSet, ns, t)
   483  	rs := newRS("rs", ns.Name, 0)
   484  	createRSsPods(t, clientSet, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   485  
   486  	// test to ensure apps/v1 selector is immutable
   487  	rsV1, err := clientSet.AppsV1().ReplicaSets(ns.Name).Get(context.TODO(), rs.Name, metav1.GetOptions{})
   488  	if err != nil {
   489  		t.Fatalf("failed to get apps/v1 replicaset %s: %v", rs.Name, err)
   490  	}
   491  	newSelectorLabels := map[string]string{"changed_name_apps_v1": "changed_test_apps_v1"}
   492  	rsV1.Spec.Selector.MatchLabels = newSelectorLabels
   493  	rsV1.Spec.Template.Labels = newSelectorLabels
   494  	_, err = clientSet.AppsV1().ReplicaSets(ns.Name).Update(context.TODO(), rsV1, metav1.UpdateOptions{})
   495  	if err == nil {
   496  		t.Fatalf("failed to provide validation error when changing immutable selector when updating apps/v1 replicaset %s", rsV1.Name)
   497  	}
   498  	expectedErrType := "Invalid value"
   499  	expectedErrDetail := "field is immutable"
   500  	if !strings.Contains(err.Error(), expectedErrType) || !strings.Contains(err.Error(), expectedErrDetail) {
   501  		t.Errorf("error message does not match, expected type: %s, expected detail: %s, got: %s", expectedErrType, expectedErrDetail, err.Error())
   502  	}
   503  }
   504  
   505  func TestSpecReplicasChange(t *testing.T) {
   506  	tCtx, closeFn, rm, informers, c := rmSetup(t)
   507  	defer closeFn()
   508  	ns := framework.CreateNamespaceOrDie(c, "test-spec-replicas-change", t)
   509  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   510  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   511  	defer stopControllers()
   512  
   513  	rs := newRS("rs", ns.Name, 2)
   514  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   515  	rs = rss[0]
   516  	waitRSStable(t, c, rs)
   517  
   518  	// Update .Spec.Replicas and verify .Status.Replicas is changed accordingly
   519  	scaleRS(t, c, rs, 3)
   520  	scaleRS(t, c, rs, 0)
   521  	scaleRS(t, c, rs, 2)
   522  
   523  	// Add a template annotation change to test RS's status does update
   524  	// without .Spec.Replicas change
   525  	rsClient := c.AppsV1().ReplicaSets(ns.Name)
   526  	var oldGeneration int64
   527  	newRS := updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
   528  		oldGeneration = rs.Generation
   529  		rs.Spec.Template.Annotations = map[string]string{"test": "annotation"}
   530  	})
   531  	savedGeneration := newRS.Generation
   532  	if savedGeneration == oldGeneration {
   533  		t.Fatalf("Failed to verify .Generation has incremented for rs %s", rs.Name)
   534  	}
   535  
   536  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   537  		newRS, err := rsClient.Get(tCtx, rs.Name, metav1.GetOptions{})
   538  		if err != nil {
   539  			return false, err
   540  		}
   541  		return newRS.Status.ObservedGeneration >= savedGeneration, nil
   542  	}); err != nil {
   543  		t.Fatalf("Failed to verify .Status.ObservedGeneration has incremented for rs %s: %v", rs.Name, err)
   544  	}
   545  }
   546  
   547  func TestDeletingAndFailedPods(t *testing.T) {
   548  	tCtx, closeFn, rm, informers, c := rmSetup(t)
   549  	defer closeFn()
   550  
   551  	ns := framework.CreateNamespaceOrDie(c, "test-deleting-and-failed-pods", t)
   552  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   553  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   554  	defer stopControllers()
   555  
   556  	rs := newRS("rs", ns.Name, 2)
   557  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   558  	rs = rss[0]
   559  	waitRSStable(t, c, rs)
   560  
   561  	// Verify RS creates 2 pods
   562  	podClient := c.CoreV1().Pods(ns.Name)
   563  	pods := getPods(t, podClient, labelMap())
   564  	if len(pods.Items) != 2 {
   565  		t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
   566  	}
   567  
   568  	// Set first pod as deleting pod
   569  	// Set finalizers for the pod to simulate pending deletion status
   570  	deletingPod := &pods.Items[0]
   571  	updatePod(t, podClient, deletingPod.Name, func(pod *v1.Pod) {
   572  		pod.Finalizers = []string{"fake.example.com/blockDeletion"}
   573  	})
   574  	if err := c.CoreV1().Pods(ns.Name).Delete(tCtx, deletingPod.Name, metav1.DeleteOptions{}); err != nil {
   575  		t.Fatalf("Error deleting pod %s: %v", deletingPod.Name, err)
   576  	}
   577  
   578  	// Set second pod as failed pod
   579  	failedPod := &pods.Items[1]
   580  	updatePodStatus(t, podClient, failedPod.Name, func(pod *v1.Pod) {
   581  		pod.Status.Phase = v1.PodFailed
   582  	})
   583  
   584  	// Pool until 2 new pods have been created to replace deleting and failed pods
   585  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   586  		pods = getPods(t, podClient, labelMap())
   587  		return len(pods.Items) == 4, nil
   588  	}); err != nil {
   589  		t.Fatalf("Failed to verify 2 new pods have been created (expected 4 pods): %v", err)
   590  	}
   591  
   592  	// Verify deleting and failed pods are among the four pods
   593  	foundDeletingPod := false
   594  	foundFailedPod := false
   595  	for _, pod := range pods.Items {
   596  		if pod.UID == deletingPod.UID {
   597  			foundDeletingPod = true
   598  		}
   599  		if pod.UID == failedPod.UID {
   600  			foundFailedPod = true
   601  		}
   602  	}
   603  	// Verify deleting pod exists
   604  	if !foundDeletingPod {
   605  		t.Fatalf("expected deleting pod %s exists, but it is not found", deletingPod.Name)
   606  	}
   607  	// Verify failed pod exists
   608  	if !foundFailedPod {
   609  		t.Fatalf("expected failed pod %s exists, but it is not found", failedPod.Name)
   610  	}
   611  }
   612  
   613  func TestPodDeletionCost(t *testing.T) {
   614  	tests := []struct {
   615  		name              string
   616  		costs             []string
   617  		restarts          []int32
   618  		enabled           bool
   619  		remainingPodIndex int
   620  	}{
   621  		{
   622  			name:              "enabled-with-different-costs",
   623  			costs:             []string{"1000", "100"},
   624  			restarts:          []int32{5, 0},
   625  			enabled:           true,
   626  			remainingPodIndex: 0,
   627  		},
   628  		{
   629  			name:              "enabled-with-same-costs",
   630  			costs:             []string{"100", "100"},
   631  			restarts:          []int32{5, 0},
   632  			enabled:           true,
   633  			remainingPodIndex: 1,
   634  		},
   635  		{
   636  			name:              "enabled-with-no-costs",
   637  			restarts:          []int32{5, 0},
   638  			enabled:           true,
   639  			remainingPodIndex: 1,
   640  		},
   641  		{
   642  			name:              "disabled-with-different-costs",
   643  			costs:             []string{"1000", "100"},
   644  			restarts:          []int32{5, 0},
   645  			enabled:           false,
   646  			remainingPodIndex: 1,
   647  		},
   648  	}
   649  	for _, tc := range tests {
   650  		t.Run(tc.name, func(t *testing.T) {
   651  			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodDeletionCost, tc.enabled)()
   652  			_, closeFn, rm, informers, c := rmSetup(t)
   653  			defer closeFn()
   654  			ns := framework.CreateNamespaceOrDie(c, tc.name, t)
   655  			defer framework.DeleteNamespaceOrDie(c, ns, t)
   656  			stopControllers := runControllerAndInformers(t, rm, informers, 0)
   657  			defer stopControllers()
   658  
   659  			rs := newRS("rs", ns.Name, 2)
   660  			rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   661  			rs = rss[0]
   662  			waitRSStable(t, c, rs)
   663  
   664  			// Verify RS creates 2 pods.
   665  			podClient := c.CoreV1().Pods(ns.Name)
   666  			pods := getPods(t, podClient, labelMap())
   667  			if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   668  				pods = getPods(t, podClient, labelMap())
   669  				return len(pods.Items) == 2, nil
   670  			}); err != nil {
   671  				t.Fatalf("Failed to verify replicaset has 2 pods: %v", err)
   672  			}
   673  
   674  			// Set a higher deletion cost to the pod that is supposed to remain after scale down.
   675  			remainingPodUID := pods.Items[tc.remainingPodIndex].UID
   676  			for i := range pods.Items {
   677  				podName := pods.Items[i].Name
   678  				if len(tc.costs) != 0 {
   679  					updatePod(t, podClient, podName, func(pod *v1.Pod) {
   680  						pod.Annotations = map[string]string{core.PodDeletionCost: tc.costs[i]}
   681  					})
   682  				}
   683  				updatePodStatus(t, podClient, podName, func(pod *v1.Pod) {
   684  					pod.Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: tc.restarts[i]}}
   685  				})
   686  			}
   687  
   688  			// Change RS's number of replics to 1
   689  			rsClient := c.AppsV1().ReplicaSets(ns.Name)
   690  			updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
   691  				rs.Spec.Replicas = ptr.To[int32](1)
   692  			})
   693  
   694  			// Poll until ReplicaSet is downscaled to 1.
   695  			if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   696  				pods = getPods(t, podClient, labelMap())
   697  				return len(pods.Items) == 1, nil
   698  			}); err != nil {
   699  				t.Fatalf("Failed to downscale replicaset to 1 pod: %v", err)
   700  			}
   701  
   702  			if pods.Items[0].UID != remainingPodUID {
   703  				t.Errorf("expected remaining Pod UID %v, got UID %v with container statues %v",
   704  					remainingPodUID, pods.Items[0].UID, pods.Items[0].Status.ContainerStatuses)
   705  			}
   706  		})
   707  	}
   708  }
   709  
   710  func TestOverlappingRSs(t *testing.T) {
   711  	tCtx, closeFn, rm, informers, c := rmSetup(t)
   712  	defer closeFn()
   713  	ns := framework.CreateNamespaceOrDie(c, "test-overlapping-rss", t)
   714  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   715  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   716  	defer stopControllers()
   717  
   718  	// Create 2 RSs with identical selectors
   719  	for i := 0; i < 2; i++ {
   720  		// One RS has 1 replica, and another has 2 replicas
   721  		rs := newRS(fmt.Sprintf("rs-%d", i+1), ns.Name, i+1)
   722  		rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   723  		waitRSStable(t, c, rss[0])
   724  	}
   725  
   726  	// Expect 3 total Pods to be created
   727  	podClient := c.CoreV1().Pods(ns.Name)
   728  	pods := getPods(t, podClient, labelMap())
   729  	if len(pods.Items) != 3 {
   730  		t.Errorf("len(pods) = %d, want 3", len(pods.Items))
   731  	}
   732  
   733  	// Expect both RSs have .status.replicas = .spec.replicas
   734  	for i := 0; i < 2; i++ {
   735  		newRS, err := c.AppsV1().ReplicaSets(ns.Name).Get(tCtx, fmt.Sprintf("rs-%d", i+1), metav1.GetOptions{})
   736  		if err != nil {
   737  			t.Fatalf("failed to obtain rs rs-%d: %v", i+1, err)
   738  		}
   739  		if newRS.Status.Replicas != *newRS.Spec.Replicas {
   740  			t.Fatalf(".Status.Replicas %d is not equal to .Spec.Replicas %d", newRS.Status.Replicas, *newRS.Spec.Replicas)
   741  		}
   742  	}
   743  }
   744  
   745  func TestPodOrphaningAndAdoptionWhenLabelsChange(t *testing.T) {
   746  	tCtx, closeFn, rm, informers, c := rmSetup(t)
   747  	defer closeFn()
   748  	ns := framework.CreateNamespaceOrDie(c, "test-pod-orphaning-and-adoption-when-labels-change", t)
   749  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   750  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   751  	defer stopControllers()
   752  
   753  	rs := newRS("rs", ns.Name, 1)
   754  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   755  	rs = rss[0]
   756  	waitRSStable(t, c, rs)
   757  
   758  	// Orphaning: RS should remove OwnerReference from a pod when the pod's labels change to not match its labels
   759  	podClient := c.CoreV1().Pods(ns.Name)
   760  	pods := getPods(t, podClient, labelMap())
   761  	if len(pods.Items) != 1 {
   762  		t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
   763  	}
   764  	pod := &pods.Items[0]
   765  
   766  	// Start by verifying ControllerRef for the pod is not nil
   767  	if metav1.GetControllerOf(pod) == nil {
   768  		t.Fatalf("ControllerRef of pod %s is nil", pod.Name)
   769  	}
   770  	newLabelMap := map[string]string{"new-foo": "new-bar"}
   771  	updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
   772  		pod.Labels = newLabelMap
   773  	})
   774  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   775  		newPod, err := podClient.Get(tCtx, pod.Name, metav1.GetOptions{})
   776  		if err != nil {
   777  			return false, err
   778  		}
   779  		pod = newPod
   780  		return metav1.GetControllerOf(newPod) == nil, nil
   781  	}); err != nil {
   782  		t.Fatalf("Failed to verify ControllerRef for the pod %s is nil: %v", pod.Name, err)
   783  	}
   784  
   785  	// Adoption: RS should add ControllerRef to a pod when the pod's labels change to match its labels
   786  	updatePod(t, podClient, pod.Name, func(pod *v1.Pod) {
   787  		pod.Labels = labelMap()
   788  	})
   789  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   790  		newPod, err := podClient.Get(tCtx, pod.Name, metav1.GetOptions{})
   791  		if err != nil {
   792  			// If the pod is not found, it means the RS picks the pod for deletion (it is extra)
   793  			// Verify there is only one pod in namespace and it has ControllerRef to the RS
   794  			if !apierrors.IsNotFound(err) {
   795  				return false, err
   796  			}
   797  
   798  			pods := getPods(t, podClient, labelMap())
   799  			if len(pods.Items) != 1 {
   800  				return false, fmt.Errorf("Expected 1 pod in current namespace, got %d", len(pods.Items))
   801  			}
   802  			// Set the pod accordingly
   803  			pod = &pods.Items[0]
   804  			return true, nil
   805  		}
   806  		// Always update the pod so that we can save a GET call to API server later
   807  		pod = newPod
   808  		// If the pod is found, verify the pod has a ControllerRef
   809  		return metav1.GetControllerOf(newPod) != nil, nil
   810  	}); err != nil {
   811  		t.Fatalf("Failed to verify ControllerRef for pod %s is not nil: %v", pod.Name, err)
   812  	}
   813  	// Verify the pod has a ControllerRef to the RS
   814  	// Do nothing if the pod is nil (i.e., has been picked for deletion)
   815  	if pod != nil {
   816  		controllerRef := metav1.GetControllerOf(pod)
   817  		if controllerRef.UID != rs.UID {
   818  			t.Fatalf("RS owner of the pod %s has a different UID: Expected %v, got %v", pod.Name, rs.UID, controllerRef.UID)
   819  		}
   820  	}
   821  }
   822  
   823  func TestGeneralPodAdoption(t *testing.T) {
   824  	_, closeFn, rm, informers, c := rmSetup(t)
   825  	defer closeFn()
   826  	ns := framework.CreateNamespaceOrDie(c, "test-general-pod-adoption", t)
   827  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   828  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   829  	defer stopControllers()
   830  
   831  	rs := newRS("rs", ns.Name, 1)
   832  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   833  	rs = rss[0]
   834  	waitRSStable(t, c, rs)
   835  
   836  	podClient := c.CoreV1().Pods(ns.Name)
   837  	pods := getPods(t, podClient, labelMap())
   838  	if len(pods.Items) != 1 {
   839  		t.Fatalf("len(pods) = %d, want 1", len(pods.Items))
   840  	}
   841  	pod := &pods.Items[0]
   842  	var falseVar = false
   843  
   844  	// When the only OwnerReference of the pod points to another type of API object such as statefulset
   845  	// with Controller=false, the RS should add a second OwnerReference (ControllerRef) pointing to itself
   846  	// with Controller=true
   847  	ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1", Kind: "StatefulSet", Name: rs.Name, Controller: &falseVar}
   848  	testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 2)
   849  
   850  	// When the only OwnerReference of the pod points to the RS, but Controller=false
   851  	ownerReference = metav1.OwnerReference{UID: rs.UID, APIVersion: "apps/v1", Kind: "ReplicaSet", Name: rs.Name, Controller: &falseVar}
   852  	testPodControllerRefPatch(t, c, pod, &ownerReference, rs, 1)
   853  }
   854  
   855  func TestReadyAndAvailableReplicas(t *testing.T) {
   856  	tCtx, closeFn, rm, informers, c := rmSetup(t)
   857  	defer closeFn()
   858  	ns := framework.CreateNamespaceOrDie(c, "test-ready-and-available-replicas", t)
   859  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   860  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   861  	defer stopControllers()
   862  
   863  	rs := newRS("rs", ns.Name, 3)
   864  	rs.Spec.MinReadySeconds = 3600
   865  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   866  	rs = rss[0]
   867  	waitRSStable(t, c, rs)
   868  
   869  	// First verify no pod is available
   870  	if rs.Status.AvailableReplicas != 0 {
   871  		t.Fatalf("Unexpected .Status.AvailableReplicas: Expected 0, saw %d", rs.Status.AvailableReplicas)
   872  	}
   873  
   874  	podClient := c.CoreV1().Pods(ns.Name)
   875  	pods := getPods(t, podClient, labelMap())
   876  	if len(pods.Items) != 3 {
   877  		t.Fatalf("len(pods) = %d, want 3", len(pods.Items))
   878  	}
   879  
   880  	// Separate 3 pods into their own list
   881  	firstPodList := &v1.PodList{Items: pods.Items[:1]}
   882  	secondPodList := &v1.PodList{Items: pods.Items[1:2]}
   883  	thirdPodList := &v1.PodList{Items: pods.Items[2:]}
   884  	// First pod: Running, but not Ready
   885  	// by setting the Ready condition to false with LastTransitionTime to be now
   886  	setPodsReadyCondition(t, c, firstPodList, v1.ConditionFalse, time.Now())
   887  	// Second pod: Running and Ready, but not Available
   888  	// by setting LastTransitionTime to now
   889  	setPodsReadyCondition(t, c, secondPodList, v1.ConditionTrue, time.Now())
   890  	// Third pod: Running, Ready, and Available
   891  	// by setting LastTransitionTime to more than 3600 seconds ago
   892  	setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute))
   893  
   894  	rsClient := c.AppsV1().ReplicaSets(ns.Name)
   895  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   896  		newRS, err := rsClient.Get(tCtx, rs.Name, metav1.GetOptions{})
   897  		if err != nil {
   898  			return false, err
   899  		}
   900  		// Verify 3 pods exist, 2 pods are Ready, and 1 pod is Available
   901  		return newRS.Status.Replicas == 3 && newRS.Status.ReadyReplicas == 2 && newRS.Status.AvailableReplicas == 1, nil
   902  	}); err != nil {
   903  		t.Fatalf("Failed to verify number of Replicas, ReadyReplicas and AvailableReplicas of rs %s to be as expected: %v", rs.Name, err)
   904  	}
   905  }
   906  
   907  func TestRSScaleSubresource(t *testing.T) {
   908  	_, closeFn, rm, informers, c := rmSetup(t)
   909  	defer closeFn()
   910  	ns := framework.CreateNamespaceOrDie(c, "test-rs-scale-subresource", t)
   911  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   912  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   913  	defer stopControllers()
   914  
   915  	rs := newRS("rs", ns.Name, 1)
   916  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   917  	rs = rss[0]
   918  	waitRSStable(t, c, rs)
   919  
   920  	// Use scale subresource to scale up .Spec.Replicas to 3
   921  	testScalingUsingScaleSubresource(t, c, rs, 3)
   922  	// Use the scale subresource to scale down .Spec.Replicas to 0
   923  	testScalingUsingScaleSubresource(t, c, rs, 0)
   924  }
   925  
   926  func TestExtraPodsAdoptionAndDeletion(t *testing.T) {
   927  	_, closeFn, rm, informers, c := rmSetup(t)
   928  	defer closeFn()
   929  	ns := framework.CreateNamespaceOrDie(c, "test-extra-pods-adoption-and-deletion", t)
   930  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   931  
   932  	rs := newRS("rs", ns.Name, 2)
   933  	// Create 3 pods, RS should adopt only 2 of them
   934  	podList := []*v1.Pod{}
   935  	for i := 0; i < 3; i++ {
   936  		pod := newMatchingPod(fmt.Sprintf("pod-%d", i+1), ns.Name)
   937  		pod.Labels = labelMap()
   938  		podList = append(podList, pod)
   939  	}
   940  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, podList)
   941  	rs = rss[0]
   942  	stopControllers := runControllerAndInformers(t, rm, informers, 3)
   943  	defer stopControllers()
   944  	waitRSStable(t, c, rs)
   945  
   946  	// Verify the extra pod is deleted eventually by determining whether number of
   947  	// all pods within namespace matches .spec.replicas of the RS (2 in this case)
   948  	podClient := c.CoreV1().Pods(ns.Name)
   949  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   950  		// All pods have labelMap as their labels
   951  		pods := getPods(t, podClient, labelMap())
   952  		return int32(len(pods.Items)) == *rs.Spec.Replicas, nil
   953  	}); err != nil {
   954  		t.Fatalf("Failed to verify number of all pods within current namespace matches .spec.replicas of rs %s: %v", rs.Name, err)
   955  	}
   956  }
   957  
   958  func TestFullyLabeledReplicas(t *testing.T) {
   959  	tCtx, closeFn, rm, informers, c := rmSetup(t)
   960  	defer closeFn()
   961  	ns := framework.CreateNamespaceOrDie(c, "test-fully-labeled-replicas", t)
   962  	defer framework.DeleteNamespaceOrDie(c, ns, t)
   963  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
   964  	defer stopControllers()
   965  
   966  	extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"}
   967  	rs := newRS("rs", ns.Name, 2)
   968  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
   969  	rs = rss[0]
   970  	waitRSStable(t, c, rs)
   971  
   972  	// Change RS's template labels to have extra labels, but not its selector
   973  	rsClient := c.AppsV1().ReplicaSets(ns.Name)
   974  	updateRS(t, rsClient, rs.Name, func(rs *apps.ReplicaSet) {
   975  		rs.Spec.Template.Labels = extraLabelMap
   976  	})
   977  
   978  	// Set one of the pods to have extra labels
   979  	podClient := c.CoreV1().Pods(ns.Name)
   980  	pods := getPods(t, podClient, labelMap())
   981  	if len(pods.Items) != 2 {
   982  		t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
   983  	}
   984  	fullyLabeledPod := &pods.Items[0]
   985  	updatePod(t, podClient, fullyLabeledPod.Name, func(pod *v1.Pod) {
   986  		pod.Labels = extraLabelMap
   987  	})
   988  
   989  	// Verify only one pod is fully labeled
   990  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
   991  		newRS, err := rsClient.Get(tCtx, rs.Name, metav1.GetOptions{})
   992  		if err != nil {
   993  			return false, err
   994  		}
   995  		return (newRS.Status.Replicas == 2 && newRS.Status.FullyLabeledReplicas == 1), nil
   996  	}); err != nil {
   997  		t.Fatalf("Failed to verify only one pod is fully labeled: %v", err)
   998  	}
   999  }
  1000  
  1001  func TestReplicaSetsAppsV1DefaultGCPolicy(t *testing.T) {
  1002  	tCtx, closeFn, rm, informers, c := rmSetup(t)
  1003  	defer closeFn()
  1004  	ns := framework.CreateNamespaceOrDie(c, "test-default-gc-v1", t)
  1005  	defer framework.DeleteNamespaceOrDie(c, ns, t)
  1006  	stopControllers := runControllerAndInformers(t, rm, informers, 0)
  1007  	defer stopControllers()
  1008  
  1009  	rs := newRS("rs", ns.Name, 2)
  1010  	fakeFinalizer := "kube.io/dummy-finalizer"
  1011  	rs.Finalizers = []string{fakeFinalizer}
  1012  	rss, _ := createRSsPods(t, c, []*apps.ReplicaSet{rs}, []*v1.Pod{})
  1013  	rs = rss[0]
  1014  	waitRSStable(t, c, rs)
  1015  
  1016  	// Verify RS creates 2 pods
  1017  	podClient := c.CoreV1().Pods(ns.Name)
  1018  	pods := getPods(t, podClient, labelMap())
  1019  	if len(pods.Items) != 2 {
  1020  		t.Fatalf("len(pods) = %d, want 2", len(pods.Items))
  1021  	}
  1022  
  1023  	rsClient := c.AppsV1().ReplicaSets(ns.Name)
  1024  	err := rsClient.Delete(tCtx, rs.Name, metav1.DeleteOptions{})
  1025  	if err != nil {
  1026  		t.Fatalf("Failed to delete rs: %v", err)
  1027  	}
  1028  
  1029  	// Verify no new finalizer has been added
  1030  	if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
  1031  		newRS, err := rsClient.Get(tCtx, rs.Name, metav1.GetOptions{})
  1032  		if err != nil {
  1033  			return false, err
  1034  		}
  1035  		if newRS.DeletionTimestamp == nil {
  1036  			return false, nil
  1037  		}
  1038  		if got, want := newRS.Finalizers, []string{fakeFinalizer}; !reflect.DeepEqual(got, want) {
  1039  			return false, fmt.Errorf("got finalizers: %+v; want: %+v", got, want)
  1040  		}
  1041  		return true, nil
  1042  	}); err != nil {
  1043  		t.Fatalf("Failed to verify the finalizer: %v", err)
  1044  	}
  1045  
  1046  	updateRS(t, c.AppsV1().ReplicaSets(ns.Name), rs.Name, func(rs *apps.ReplicaSet) {
  1047  		var finalizers []string
  1048  		// remove fakeFinalizer
  1049  		for _, finalizer := range rs.Finalizers {
  1050  			if finalizer != fakeFinalizer {
  1051  				finalizers = append(finalizers, finalizer)
  1052  			}
  1053  		}
  1054  		rs.Finalizers = finalizers
  1055  	})
  1056  
  1057  	_ = rsClient.Delete(tCtx, rs.Name, metav1.DeleteOptions{})
  1058  }
  1059  

View as plain text