mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 10:18:13 +00:00 
			
		
		
		
	 aa89e6dc97
			
		
	
	aa89e6dc97
	
	
	
		
			
			This uses the generic ptr.To in k8s.io/utils to replace functions and code constructs which only serve to return pointers to intstr values. Other uses of the deprecated pointer package are updated in modified files. Signed-off-by: Stephen Kitt <skitt@redhat.com>
		
			
				
	
	
		
			387 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			387 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2016 The Kubernetes Authors.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package deployment
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"testing"
 | |
| 
 | |
| 	apps "k8s.io/api/apps/v1"
 | |
| 	"k8s.io/apimachinery/pkg/util/intstr"
 | |
| 	"k8s.io/client-go/kubernetes/fake"
 | |
| 	core "k8s.io/client-go/testing"
 | |
| 	"k8s.io/client-go/tools/record"
 | |
| 	"k8s.io/klog/v2/ktesting"
 | |
| )
 | |
| 
 | |
| func TestDeploymentController_reconcileNewReplicaSet(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		deploymentReplicas  int32
 | |
| 		maxSurge            intstr.IntOrString
 | |
| 		oldReplicas         int32
 | |
| 		newReplicas         int32
 | |
| 		scaleExpected       bool
 | |
| 		expectedNewReplicas int32
 | |
| 	}{
 | |
| 		{
 | |
| 			// Should not scale up.
 | |
| 			deploymentReplicas: 10,
 | |
| 			maxSurge:           intstr.FromInt32(0),
 | |
| 			oldReplicas:        10,
 | |
| 			newReplicas:        0,
 | |
| 			scaleExpected:      false,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxSurge:            intstr.FromInt32(2),
 | |
| 			oldReplicas:         10,
 | |
| 			newReplicas:         0,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedNewReplicas: 2,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxSurge:            intstr.FromInt32(2),
 | |
| 			oldReplicas:         5,
 | |
| 			newReplicas:         0,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedNewReplicas: 7,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas: 10,
 | |
| 			maxSurge:           intstr.FromInt32(2),
 | |
| 			oldReplicas:        10,
 | |
| 			newReplicas:        2,
 | |
| 			scaleExpected:      false,
 | |
| 		},
 | |
| 		{
 | |
| 			// Should scale down.
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxSurge:            intstr.FromInt32(2),
 | |
| 			oldReplicas:         2,
 | |
| 			newReplicas:         11,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedNewReplicas: 10,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for i := range tests {
 | |
| 		test := tests[i]
 | |
| 		t.Logf("executing scenario %d", i)
 | |
| 		newRS := rs("foo-v2", test.newReplicas, nil, noTimestamp)
 | |
| 		oldRS := rs("foo-v2", test.oldReplicas, nil, noTimestamp)
 | |
| 		allRSs := []*apps.ReplicaSet{newRS, oldRS}
 | |
| 		maxUnavailable := intstr.FromInt32(0)
 | |
| 		deployment := newDeployment("foo", test.deploymentReplicas, nil, &test.maxSurge, &maxUnavailable, map[string]string{"foo": "bar"})
 | |
| 		fake := fake.Clientset{}
 | |
| 		controller := &DeploymentController{
 | |
| 			client:        &fake,
 | |
| 			eventRecorder: &record.FakeRecorder{},
 | |
| 		}
 | |
| 		_, ctx := ktesting.NewTestContext(t)
 | |
| 		ctx, cancel := context.WithCancel(ctx)
 | |
| 		defer cancel()
 | |
| 		scaled, err := controller.reconcileNewReplicaSet(ctx, allRSs, newRS, deployment)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("unexpected error: %v", err)
 | |
| 			continue
 | |
| 		}
 | |
| 		if !test.scaleExpected {
 | |
| 			if scaled || len(fake.Actions()) > 0 {
 | |
| 				t.Errorf("unexpected scaling: %v", fake.Actions())
 | |
| 			}
 | |
| 			continue
 | |
| 		}
 | |
| 		if test.scaleExpected && !scaled {
 | |
| 			t.Errorf("expected scaling to occur")
 | |
| 			continue
 | |
| 		}
 | |
| 		if len(fake.Actions()) != 1 {
 | |
| 			t.Errorf("expected 1 action during scale, got: %v", fake.Actions())
 | |
| 			continue
 | |
| 		}
 | |
| 		updated := fake.Actions()[0].(core.UpdateAction).GetObject().(*apps.ReplicaSet)
 | |
| 		if e, a := test.expectedNewReplicas, *(updated.Spec.Replicas); e != a {
 | |
| 			t.Errorf("expected update to %d replicas, got %d", e, a)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDeploymentController_reconcileOldReplicaSets(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		deploymentReplicas  int32
 | |
| 		maxUnavailable      intstr.IntOrString
 | |
| 		oldReplicas         int32
 | |
| 		newReplicas         int32
 | |
| 		readyPodsFromOldRS  int
 | |
| 		readyPodsFromNewRS  int
 | |
| 		scaleExpected       bool
 | |
| 		expectedOldReplicas int32
 | |
| 	}{
 | |
| 		{
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxUnavailable:      intstr.FromInt32(0),
 | |
| 			oldReplicas:         10,
 | |
| 			newReplicas:         0,
 | |
| 			readyPodsFromOldRS:  10,
 | |
| 			readyPodsFromNewRS:  0,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedOldReplicas: 9,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxUnavailable:      intstr.FromInt32(2),
 | |
| 			oldReplicas:         10,
 | |
| 			newReplicas:         0,
 | |
| 			readyPodsFromOldRS:  10,
 | |
| 			readyPodsFromNewRS:  0,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedOldReplicas: 8,
 | |
| 		},
 | |
| 		{ // expect unhealthy replicas from old replica sets been cleaned up
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxUnavailable:      intstr.FromInt32(2),
 | |
| 			oldReplicas:         10,
 | |
| 			newReplicas:         0,
 | |
| 			readyPodsFromOldRS:  8,
 | |
| 			readyPodsFromNewRS:  0,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedOldReplicas: 8,
 | |
| 		},
 | |
| 		{ // expect 1 unhealthy replica from old replica sets been cleaned up, and 1 ready pod been scaled down
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxUnavailable:      intstr.FromInt32(2),
 | |
| 			oldReplicas:         10,
 | |
| 			newReplicas:         0,
 | |
| 			readyPodsFromOldRS:  9,
 | |
| 			readyPodsFromNewRS:  0,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedOldReplicas: 8,
 | |
| 		},
 | |
| 		{ // the unavailable pods from the newRS would not make us scale down old RSs in a further step
 | |
| 			deploymentReplicas: 10,
 | |
| 			maxUnavailable:     intstr.FromInt32(2),
 | |
| 			oldReplicas:        8,
 | |
| 			newReplicas:        2,
 | |
| 			readyPodsFromOldRS: 8,
 | |
| 			readyPodsFromNewRS: 0,
 | |
| 			scaleExpected:      false,
 | |
| 		},
 | |
| 	}
 | |
| 	for i := range tests {
 | |
| 		test := tests[i]
 | |
| 		t.Logf("executing scenario %d", i)
 | |
| 
 | |
| 		newSelector := map[string]string{"foo": "new"}
 | |
| 		oldSelector := map[string]string{"foo": "old"}
 | |
| 		newRS := rs("foo-new", test.newReplicas, newSelector, noTimestamp)
 | |
| 		newRS.Status.AvailableReplicas = int32(test.readyPodsFromNewRS)
 | |
| 		oldRS := rs("foo-old", test.oldReplicas, oldSelector, noTimestamp)
 | |
| 		oldRS.Status.AvailableReplicas = int32(test.readyPodsFromOldRS)
 | |
| 		oldRSs := []*apps.ReplicaSet{oldRS}
 | |
| 		allRSs := []*apps.ReplicaSet{oldRS, newRS}
 | |
| 		maxSurge := intstr.FromInt32(0)
 | |
| 		deployment := newDeployment("foo", test.deploymentReplicas, nil, &maxSurge, &test.maxUnavailable, newSelector)
 | |
| 		fakeClientset := fake.Clientset{}
 | |
| 		controller := &DeploymentController{
 | |
| 			client:        &fakeClientset,
 | |
| 			eventRecorder: &record.FakeRecorder{},
 | |
| 		}
 | |
| 		_, ctx := ktesting.NewTestContext(t)
 | |
| 		scaled, err := controller.reconcileOldReplicaSets(ctx, allRSs, oldRSs, newRS, deployment)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("unexpected error: %v", err)
 | |
| 			continue
 | |
| 		}
 | |
| 		if !test.scaleExpected && scaled {
 | |
| 			t.Errorf("unexpected scaling: %v", fakeClientset.Actions())
 | |
| 		}
 | |
| 		if test.scaleExpected && !scaled {
 | |
| 			t.Errorf("expected scaling to occur")
 | |
| 			continue
 | |
| 		}
 | |
| 		continue
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDeploymentController_cleanupUnhealthyReplicas(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		oldReplicas          int32
 | |
| 		readyPods            int
 | |
| 		unHealthyPods        int
 | |
| 		maxCleanupCount      int
 | |
| 		cleanupCountExpected int
 | |
| 	}{
 | |
| 		{
 | |
| 			oldReplicas:          10,
 | |
| 			readyPods:            8,
 | |
| 			unHealthyPods:        2,
 | |
| 			maxCleanupCount:      1,
 | |
| 			cleanupCountExpected: 1,
 | |
| 		},
 | |
| 		{
 | |
| 			oldReplicas:          10,
 | |
| 			readyPods:            8,
 | |
| 			unHealthyPods:        2,
 | |
| 			maxCleanupCount:      3,
 | |
| 			cleanupCountExpected: 2,
 | |
| 		},
 | |
| 		{
 | |
| 			oldReplicas:          10,
 | |
| 			readyPods:            8,
 | |
| 			unHealthyPods:        2,
 | |
| 			maxCleanupCount:      0,
 | |
| 			cleanupCountExpected: 0,
 | |
| 		},
 | |
| 		{
 | |
| 			oldReplicas:          10,
 | |
| 			readyPods:            10,
 | |
| 			unHealthyPods:        0,
 | |
| 			maxCleanupCount:      3,
 | |
| 			cleanupCountExpected: 0,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for i, test := range tests {
 | |
| 		t.Logf("executing scenario %d", i)
 | |
| 		oldRS := rs("foo-v2", test.oldReplicas, nil, noTimestamp)
 | |
| 		oldRS.Status.AvailableReplicas = int32(test.readyPods)
 | |
| 		oldRSs := []*apps.ReplicaSet{oldRS}
 | |
| 		maxSurge := intstr.FromInt32(2)
 | |
| 		maxUnavailable := intstr.FromInt32(2)
 | |
| 		deployment := newDeployment("foo", 10, nil, &maxSurge, &maxUnavailable, nil)
 | |
| 		fakeClientset := fake.Clientset{}
 | |
| 
 | |
| 		controller := &DeploymentController{
 | |
| 			client:        &fakeClientset,
 | |
| 			eventRecorder: &record.FakeRecorder{},
 | |
| 		}
 | |
| 		_, ctx := ktesting.NewTestContext(t)
 | |
| 		_, cleanupCount, err := controller.cleanupUnhealthyReplicas(ctx, oldRSs, deployment, int32(test.maxCleanupCount))
 | |
| 		if err != nil {
 | |
| 			t.Errorf("unexpected error: %v", err)
 | |
| 			continue
 | |
| 		}
 | |
| 		if int(cleanupCount) != test.cleanupCountExpected {
 | |
| 			t.Errorf("expected %v unhealthy replicas been cleaned up, got %v", test.cleanupCountExpected, cleanupCount)
 | |
| 			continue
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDeploymentController_scaleDownOldReplicaSetsForRollingUpdate(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		deploymentReplicas  int32
 | |
| 		maxUnavailable      intstr.IntOrString
 | |
| 		readyPods           int
 | |
| 		oldReplicas         int32
 | |
| 		scaleExpected       bool
 | |
| 		expectedOldReplicas int32
 | |
| 	}{
 | |
| 		{
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxUnavailable:      intstr.FromInt32(0),
 | |
| 			readyPods:           10,
 | |
| 			oldReplicas:         10,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedOldReplicas: 9,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas:  10,
 | |
| 			maxUnavailable:      intstr.FromInt32(2),
 | |
| 			readyPods:           10,
 | |
| 			oldReplicas:         10,
 | |
| 			scaleExpected:       true,
 | |
| 			expectedOldReplicas: 8,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas: 10,
 | |
| 			maxUnavailable:     intstr.FromInt32(2),
 | |
| 			readyPods:          8,
 | |
| 			oldReplicas:        10,
 | |
| 			scaleExpected:      false,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas: 10,
 | |
| 			maxUnavailable:     intstr.FromInt32(2),
 | |
| 			readyPods:          10,
 | |
| 			oldReplicas:        0,
 | |
| 			scaleExpected:      false,
 | |
| 		},
 | |
| 		{
 | |
| 			deploymentReplicas: 10,
 | |
| 			maxUnavailable:     intstr.FromInt32(2),
 | |
| 			readyPods:          1,
 | |
| 			oldReplicas:        10,
 | |
| 			scaleExpected:      false,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for i := range tests {
 | |
| 		test := tests[i]
 | |
| 		t.Logf("executing scenario %d", i)
 | |
| 		oldRS := rs("foo-v2", test.oldReplicas, nil, noTimestamp)
 | |
| 		oldRS.Status.AvailableReplicas = int32(test.readyPods)
 | |
| 		allRSs := []*apps.ReplicaSet{oldRS}
 | |
| 		oldRSs := []*apps.ReplicaSet{oldRS}
 | |
| 		maxSurge := intstr.FromInt32(0)
 | |
| 		deployment := newDeployment("foo", test.deploymentReplicas, nil, &maxSurge, &test.maxUnavailable, map[string]string{"foo": "bar"})
 | |
| 		fakeClientset := fake.Clientset{}
 | |
| 		controller := &DeploymentController{
 | |
| 			client:        &fakeClientset,
 | |
| 			eventRecorder: &record.FakeRecorder{},
 | |
| 		}
 | |
| 		_, ctx := ktesting.NewTestContext(t)
 | |
| 		scaled, err := controller.scaleDownOldReplicaSetsForRollingUpdate(ctx, allRSs, oldRSs, deployment)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("unexpected error: %v", err)
 | |
| 			continue
 | |
| 		}
 | |
| 		if !test.scaleExpected {
 | |
| 			if scaled != 0 {
 | |
| 				t.Errorf("unexpected scaling: %v", fakeClientset.Actions())
 | |
| 			}
 | |
| 			continue
 | |
| 		}
 | |
| 		if test.scaleExpected && scaled == 0 {
 | |
| 			t.Errorf("expected scaling to occur; actions: %v", fakeClientset.Actions())
 | |
| 			continue
 | |
| 		}
 | |
| 		// There are both list and update actions logged, so extract the update
 | |
| 		// action for verification.
 | |
| 		var updateAction core.UpdateAction
 | |
| 		for _, action := range fakeClientset.Actions() {
 | |
| 			switch a := action.(type) {
 | |
| 			case core.UpdateAction:
 | |
| 				if updateAction != nil {
 | |
| 					t.Errorf("expected only 1 update action; had %v and found %v", updateAction, a)
 | |
| 				} else {
 | |
| 					updateAction = a
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if updateAction == nil {
 | |
| 			t.Errorf("expected an update action")
 | |
| 			continue
 | |
| 		}
 | |
| 		updated := updateAction.GetObject().(*apps.ReplicaSet)
 | |
| 		if e, a := test.expectedOldReplicas, *(updated.Spec.Replicas); e != a {
 | |
| 			t.Errorf("expected update to %d replicas, got %d", e, a)
 | |
| 		}
 | |
| 	}
 | |
| }
 |