From ccd53e4eebb9e5b4daaaf7d125e4434517d887af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Wed, 11 Feb 2026 15:12:44 +0300 Subject: [PATCH] Reflect expected replica count to the output of kubectl scale --- .../src/k8s.io/kubectl/pkg/cmd/scale/scale.go | 32 ++++++++- staging/src/k8s.io/kubectl/pkg/scale/scale.go | 31 +++++---- .../k8s.io/kubectl/pkg/scale/scale_test.go | 68 +++++++++++++------ test/cmd/legacy-script.sh | 7 ++ test/cmd/scale.sh | 62 +++++++++++++++++ test/utils/update_resources.go | 2 +- 6 files changed, 164 insertions(+), 38 deletions(-) create mode 100644 test/cmd/scale.sh diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/scale/scale.go b/staging/src/k8s.io/kubectl/pkg/cmd/scale/scale.go index 31d4212ec2b..d2618f5d305 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/scale/scale.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/scale/scale.go @@ -24,6 +24,7 @@ import ( "k8s.io/klog/v2" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericiooptions" @@ -238,13 +239,22 @@ func (o *ScaleOptions) RunScale() error { for _, info := range infos { mapping := info.ResourceMapping() if o.dryRunStrategy == cmdutil.DryRunClient { + if err = updateReplicas(info, int64(o.Replicas)); err != nil { + return err + } + if err := o.PrintObj(info.Object, o.Out); err != nil { return err } continue } - if err := o.scaler.Scale(info.Namespace, info.Name, uint(o.Replicas), precondition, retry, waitForReplicas, mapping.Resource, o.dryRunStrategy == cmdutil.DryRunServer); err != nil { + actualSize := new(int32) + if err := o.scaler.Scale(info.Namespace, info.Name, uint(o.Replicas), actualSize, precondition, retry, waitForReplicas, mapping.Resource, o.dryRunStrategy == cmdutil.DryRunServer); err != nil { + return err + } + + if err = updateReplicas(info, int64(*actualSize)); err != nil { return err } @@ -279,3 +289,23 @@ func scaler(f cmdutil.Factory) (scale.Scaler, error) { return scale.NewScaler(scalesGetter), nil } + +// updateReplicas updates spec.replicas for built-in scalable types. +// replicas needs to be in int64, as SetNestedField only supports this type (and float64). +func updateReplicas(info *resource.Info, replicas int64) error { + unstructuredObj, ok := info.Object.(*unstructured.Unstructured) + if !ok { + return nil + } + + // Only update for built-in types where spec.replicas is guaranteed: + // - apps group: Deployment, ReplicaSet, StatefulSet + // - core group: ReplicationController + // Skip other groups (e.g., CRDs) as they may define replicas at a different path. + gvk := unstructuredObj.GroupVersionKind() + if gvk.Group != "apps" && gvk.Group != "" { + return nil + } + + return unstructured.SetNestedField(unstructuredObj.Object, replicas, "spec", "replicas") +} diff --git a/staging/src/k8s.io/kubectl/pkg/scale/scale.go b/staging/src/k8s.io/kubectl/pkg/scale/scale.go index d2dc51fc69a..fd559353622 100644 --- a/staging/src/k8s.io/kubectl/pkg/scale/scale.go +++ b/staging/src/k8s.io/kubectl/pkg/scale/scale.go @@ -39,10 +39,10 @@ type Scaler interface { // retries in the event of resource version mismatch (if retry is not nil), // and optionally waits until the status of the resource matches newSize (if wait is not nil) // TODO: Make the implementation of this watch-based (#56075) once #31345 is fixed. - Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, wait *RetryParams, gvr schema.GroupVersionResource, dryRun bool) error + Scale(namespace, name string, newSize uint, actualSize *int32, preconditions *ScalePrecondition, retry, wait *RetryParams, gvr schema.GroupVersionResource, dryRun bool) error // ScaleSimple does a simple one-shot attempt at scaling - not useful on its own, but // a necessary building block for Scale - ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint, gvr schema.GroupVersionResource, dryRun bool) (updatedResourceVersion string, err error) + ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint, gvr schema.GroupVersionResource, dryRun bool) (updatedResourceVersion string, actualSize int32, err error) } // NewScaler get a scaler for a given resource @@ -81,12 +81,15 @@ func NewRetryParams(interval, timeout time.Duration) *RetryParams { } // ScaleCondition is a closure around Scale that facilitates retries via util.wait -func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name string, count uint, updatedResourceVersion *string, gvr schema.GroupVersionResource, dryRun bool) wait.ConditionWithContextFunc { +func ScaleCondition(r Scaler, precondition *ScalePrecondition, namespace, name string, count uint, updatedResourceVersion *string, actualSize *int32, gvr schema.GroupVersionResource, dryRun bool) wait.ConditionWithContextFunc { return func(context.Context) (bool, error) { - rv, err := r.ScaleSimple(namespace, name, precondition, count, gvr, dryRun) + rv, size, err := r.ScaleSimple(namespace, name, precondition, count, gvr, dryRun) if updatedResourceVersion != nil { *updatedResourceVersion = rv } + if actualSize != nil { + *actualSize = size + } // Retry only on update conflicts. if apierrors.IsConflict(err) { return false, nil @@ -117,14 +120,14 @@ type genericScaler struct { var _ Scaler = &genericScaler{} // ScaleSimple updates a scale of a given resource. It returns the resourceVersion of the scale if the update was successful. -func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint, gvr schema.GroupVersionResource, dryRun bool) (updatedResourceVersion string, err error) { +func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint, gvr schema.GroupVersionResource, dryRun bool) (updatedResourceVersion string, actualSize int32, err error) { if preconditions != nil { scale, err := s.scaleNamespacer.Scales(namespace).Get(context.TODO(), gvr.GroupResource(), name, metav1.GetOptions{}) if err != nil { - return "", err + return "", 0, err } if err = preconditions.validate(scale); err != nil { - return "", err + return "", 0, err } scale.Spec.Replicas = int32(newSize) updateOptions := metav1.UpdateOptions{} @@ -133,9 +136,9 @@ func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *Scale } updatedScale, err := s.scaleNamespacer.Scales(namespace).Update(context.TODO(), gvr.GroupResource(), scale, updateOptions) if err != nil { - return "", err + return "", 0, err } - return updatedScale.ResourceVersion, nil + return updatedScale.ResourceVersion, updatedScale.Spec.Replicas, nil } // objectForReplicas is used for encoding scale patch @@ -151,7 +154,7 @@ func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *Scale } patch, err := json.Marshal(&spec) if err != nil { - return "", err + return "", 0, err } patchOptions := metav1.PatchOptions{} if dryRun { @@ -159,19 +162,19 @@ func (s *genericScaler) ScaleSimple(namespace, name string, preconditions *Scale } updatedScale, err := s.scaleNamespacer.Scales(namespace).Patch(context.TODO(), gvr, name, types.MergePatchType, patch, patchOptions) if err != nil { - return "", err + return "", 0, err } - return updatedScale.ResourceVersion, nil + return updatedScale.ResourceVersion, updatedScale.Spec.Replicas, nil } // Scale updates a scale of a given resource to a new size, with optional precondition check (if preconditions is not nil), // optional retries (if retry is not nil), and then optionally waits for the status to reach desired count. -func (s *genericScaler) Scale(namespace, resourceName string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams, gvr schema.GroupVersionResource, dryRun bool) error { +func (s *genericScaler) Scale(namespace, resourceName string, newSize uint, actualSize *int32, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams, gvr schema.GroupVersionResource, dryRun bool) error { if retry == nil { // make it try only once, immediately retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} } - cond := ScaleCondition(s, preconditions, namespace, resourceName, newSize, nil, gvr, dryRun) + cond := ScaleCondition(s, preconditions, namespace, resourceName, newSize, nil, actualSize, gvr, dryRun) if err := wait.PollUntilContextTimeout(context.Background(), retry.Interval, retry.Timeout, true, cond); err != nil { return err } diff --git a/staging/src/k8s.io/kubectl/pkg/scale/scale_test.go b/staging/src/k8s.io/kubectl/pkg/scale/scale_test.go index ab3f37f8f3f..8931f17dcb3 100644 --- a/staging/src/k8s.io/kubectl/pkg/scale/scale_test.go +++ b/staging/src/k8s.io/kubectl/pkg/scale/scale_test.go @@ -69,7 +69,8 @@ func TestReplicationControllerScaleRetry(t *testing.T) { name := "foo-v1" namespace := metav1.NamespaceDefault - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, rcgvr, false) + actualSize := new(int32) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, actualSize, rcgvr, false) pass, err := scaleFunc(context.Background()) if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -78,7 +79,7 @@ func TestReplicationControllerScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update conflict failure, got %v", err) } preconditions := ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, &preconditions, namespace, name, count, nil, rcgvr, false) + scaleFunc = ScaleCondition(scaler, &preconditions, namespace, name, count, nil, actualSize, rcgvr, false) _, err = scaleFunc(context.Background()) if err == nil { t.Errorf("Expected error on precondition failure") @@ -105,7 +106,7 @@ func TestReplicationControllerScaleInvalid(t *testing.T) { name := "foo-v1" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, rcgvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, rcgvr, false) pass, err := scaleFunc(context.Background()) if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -130,11 +131,15 @@ func TestReplicationControllerScale(t *testing.T) { scaler := NewScaler(scaleClient) count := uint(3) name := "foo-v1" - err := scaler.Scale("default", name, count, nil, nil, nil, rcgvr, false) + actualSize := new(int32) + err := scaler.Scale("default", name, count, actualSize, nil, nil, nil, rcgvr, false) if err != nil { t.Fatalf("unexpected error occurred = %v while scaling the resource", err) } + if *actualSize != 3 { + t.Errorf("expected actualSize to be 3, got %d", *actualSize) + } actions := scaleClient.Actions() if len(actions) != len(scaleClientExpectedAction) { t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) @@ -153,7 +158,7 @@ func TestReplicationControllerScaleFailsPreconditions(t *testing.T) { preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, &preconditions, nil, nil, rcgvr, false) + err := scaler.Scale("default", name, count, nil, &preconditions, nil, nil, rcgvr, false) if err == nil { t.Fatal("expected to get an error but none was returned") } @@ -179,7 +184,7 @@ func TestDeploymentScaleRetry(t *testing.T) { name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, deploygvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, deploygvr, false) pass, err := scaleFunc(context.Background()) if pass != false { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -188,7 +193,7 @@ func TestDeploymentScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update failure, got %v", err) } preconditions := &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, deploygvr, false) + scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, nil, deploygvr, false) _, err = scaleFunc(context.Background()) if err == nil { t.Error("Expected error on precondition failure") @@ -210,10 +215,14 @@ func TestDeploymentScale(t *testing.T) { scaler := NewScaler(scaleClient) count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, nil, nil, nil, deploygvr, false) + actualSize := new(int32) + err := scaler.Scale("default", name, count, actualSize, nil, nil, nil, deploygvr, false) if err != nil { t.Fatal(err) } + if *actualSize != 3 { + t.Errorf("expected actualSize to be 3, got %d", *actualSize) + } actions := scaleClient.Actions() if len(actions) != len(scaleClientExpectedAction) { t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) @@ -236,7 +245,7 @@ func TestDeploymentScaleInvalid(t *testing.T) { name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, deploygvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, deploygvr, false) pass, err := scaleFunc(context.Background()) if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -262,7 +271,7 @@ func TestDeploymentScaleFailsPreconditions(t *testing.T) { preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, &preconditions, nil, nil, deploygvr, false) + err := scaler.Scale("default", name, count, nil, &preconditions, nil, nil, deploygvr, false) if err == nil { t.Fatal("exptected to get an error but none was returned") } @@ -283,10 +292,14 @@ func TestStatefulSetScale(t *testing.T) { scaler := NewScaler(scaleClient) count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, nil, nil, nil, stsgvr, false) + actualSize := new(int32) + err := scaler.Scale("default", name, count, actualSize, nil, nil, nil, stsgvr, false) if err != nil { t.Fatal(err) } + if *actualSize != 3 { + t.Errorf("expected actualSize to be 3, got %d", *actualSize) + } actions := scaleClient.Actions() if len(actions) != len(scaleClientExpectedAction) { t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) @@ -309,7 +322,7 @@ func TestStatefulSetScaleRetry(t *testing.T) { name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, stsgvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, stsgvr, false) pass, err := scaleFunc(context.Background()) if pass != false { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -318,7 +331,7 @@ func TestStatefulSetScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update failure, got %v", err) } preconditions := &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, stsgvr, false) + scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, nil, stsgvr, false) _, err = scaleFunc(context.Background()) if err == nil { t.Error("Expected error on precondition failure") @@ -345,7 +358,7 @@ func TestStatefulSetScaleInvalid(t *testing.T) { name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, stsgvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, stsgvr, false) pass, err := scaleFunc(context.Background()) if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -371,7 +384,7 @@ func TestStatefulSetScaleFailsPreconditions(t *testing.T) { preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, &preconditions, nil, nil, stsgvr, false) + err := scaler.Scale("default", name, count, nil, &preconditions, nil, nil, stsgvr, false) if err == nil { t.Fatal("expected to get an error but none was returned") } @@ -392,10 +405,14 @@ func TestReplicaSetScale(t *testing.T) { scaler := NewScaler(scaleClient) count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, nil, nil, nil, rsgvr, false) + actualSize := new(int32) + err := scaler.Scale("default", name, count, actualSize, nil, nil, nil, rsgvr, false) if err != nil { t.Fatal(err) } + if *actualSize != 3 { + t.Errorf("expected actualSize to be 3, got %d", *actualSize) + } actions := scaleClient.Actions() if len(actions) != len(scaleClientExpectedAction) { t.Errorf("unexpected actions: %v, expected %d actions got %d", actions, len(scaleClientExpectedAction), len(actions)) @@ -418,7 +435,7 @@ func TestReplicaSetScaleRetry(t *testing.T) { name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, rsgvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, rsgvr, false) pass, err := scaleFunc(context.Background()) if pass != false { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -427,7 +444,7 @@ func TestReplicaSetScaleRetry(t *testing.T) { t.Errorf("Did not expect an error on update failure, got %v", err) } preconditions := &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, rsgvr, false) + scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count, nil, nil, rsgvr, false) _, err = scaleFunc(context.Background()) if err == nil { t.Error("Expected error on precondition failure") @@ -454,7 +471,7 @@ func TestReplicaSetScaleInvalid(t *testing.T) { name := "foo" namespace := "default" - scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, rsgvr, false) + scaleFunc := ScaleCondition(scaler, nil, namespace, name, count, nil, nil, rsgvr, false) pass, err := scaleFunc(context.Background()) if pass { t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) @@ -480,7 +497,7 @@ func TestReplicaSetsGetterFailsPreconditions(t *testing.T) { preconditions := ScalePrecondition{2, ""} count := uint(3) name := "foo" - err := scaler.Scale("default", name, count, &preconditions, nil, nil, rsgvr, false) + err := scaler.Scale("default", name, count, nil, &preconditions, nil, nil, rsgvr, false) if err == nil { t.Fatal("expected to get an error but non was returned") } @@ -576,7 +593,7 @@ func TestGenericScaleSimple(t *testing.T) { t.Run(fmt.Sprintf("running scenario %d: %s", index+1, scenario.name), func(t *testing.T) { target := NewScaler(scenario.scaleGetter) - resVersion, err := target.ScaleSimple("default", scenario.resName, scenario.precondition, uint(scenario.newSize), scenario.targetGVR, false) + resVersion, actualSize, err := target.ScaleSimple("default", scenario.resName, scenario.precondition, uint(scenario.newSize), scenario.targetGVR, false) if scenario.expectError && err == nil { t.Fatal("expected an error but was not returned") @@ -584,6 +601,9 @@ func TestGenericScaleSimple(t *testing.T) { if !scenario.expectError && err != nil { t.Fatalf("unexpected error: %v", err) } + if !scenario.expectError && actualSize != int32(scenario.newSize) { + t.Errorf("expected actualSize to be %d, got %d", scenario.newSize, actualSize) + } if resVersion != "" { t.Fatalf("unexpected resource version returned = %s, wanted = %s", resVersion, "") } @@ -666,7 +686,8 @@ func TestGenericScale(t *testing.T) { t.Run(scenario.name, func(t *testing.T) { target := NewScaler(scenario.scaleGetter) - err := target.Scale("default", scenario.resName, uint(scenario.newSize), scenario.precondition, nil, scenario.waitForReplicas, scenario.targetGVR, false) + actualSize := new(int32) + err := target.Scale("default", scenario.resName, uint(scenario.newSize), actualSize, scenario.precondition, nil, scenario.waitForReplicas, scenario.targetGVR, false) if scenario.expectError && err == nil { t.Fatal("expected an error but was not returned") @@ -674,6 +695,9 @@ func TestGenericScale(t *testing.T) { if !scenario.expectError && err != nil { t.Fatalf("unexpected error: %v", err) } + if !scenario.expectError && *actualSize != int32(scenario.newSize) { + t.Errorf("expected actualSize to be %d, got %d", scenario.newSize, *actualSize) + } }) } diff --git a/test/cmd/legacy-script.sh b/test/cmd/legacy-script.sh index c0f83437b16..3759be2b1d1 100755 --- a/test/cmd/legacy-script.sh +++ b/test/cmd/legacy-script.sh @@ -57,6 +57,7 @@ source "${KUBE_ROOT}/test/cmd/request-timeout.sh" source "${KUBE_ROOT}/test/cmd/results.sh" source "${KUBE_ROOT}/test/cmd/run.sh" source "${KUBE_ROOT}/test/cmd/save-config.sh" +source "${KUBE_ROOT}/test/cmd/scale.sh" source "${KUBE_ROOT}/test/cmd/storage.sh" source "${KUBE_ROOT}/test/cmd/template-output.sh" source "${KUBE_ROOT}/test/cmd/version.sh" @@ -1064,5 +1065,11 @@ runTests() { record_command run_kuberc_tests + ########### + # Scale # + ########### + + record_command run_kubectl_scale_tests + cleanup_tests } diff --git a/test/cmd/scale.sh b/test/cmd/scale.sh new file mode 100644 index 00000000000..9fd46ef67a8 --- /dev/null +++ b/test/cmd/scale.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +# Copyright 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. + +set -o errexit +set -o nounset +set -o pipefail + +run_kubectl_scale_tests() { + set -o nounset + set -o errexit + + kube::log::status "Testing kubectl scale" + + create_and_use_new_namespace + + kube::log::status "Testing kubectl scale output for Deployment" + kubectl create deployment test-scale-deploy --image=busybox + output_message=$(kubectl scale deployment test-scale-deploy --replicas=2 --dry-run=client -o yaml) + kube::test::if_has_string "${output_message}" 'replicas: 2' + kube::test::get_object_assert 'deployment test-scale-deploy' '{{.spec.replicas}}' '1' + output_message=$(kubectl scale deployment test-scale-deploy --replicas=3 --dry-run=server -o yaml) + kube::test::if_has_string "${output_message}" 'replicas: 3' + kube::test::get_object_assert 'deployment test-scale-deploy' '{{.spec.replicas}}' '1' + output_message=$(kubectl scale deployment test-scale-deploy --replicas=2 -o yaml) + kube::test::if_has_string "${output_message}" 'replicas: 2' + kube::test::get_object_assert 'deployment test-scale-deploy' '{{.spec.replicas}}' '2' + kubectl delete deployment test-scale-deploy + + kube::log::status "Testing kubectl scale output for ReplicaSet" + kubectl create -f hack/testdata/frontend-replicaset.yaml + output_message=$(kubectl scale -f hack/testdata/frontend-replicaset.yaml --replicas=2 -o yaml) + kube::test::if_has_string "${output_message}" 'replicas: 2' + kubectl delete rs frontend + + kube::log::status "Testing kubectl scale output for ReplicationController" + kubectl create -f hack/testdata/frontend-controller.yaml + output_message=$(kubectl scale rc frontend --replicas=3 -o yaml) + kube::test::if_has_string "${output_message}" 'replicas: 3' + kubectl delete rc frontend + + kube::log::status "Testing kubectl scale output for StatefulSet" + kubectl create -f hack/testdata/rollingupdate-statefulset.yaml + output_message=$(kubectl scale statefulset nginx --replicas=2 -o yaml) + kube::test::if_has_string "${output_message}" 'replicas: 2' + kubectl delete statefulset nginx + + set +o nounset + set +o errexit +} diff --git a/test/utils/update_resources.go b/test/utils/update_resources.go index af5a59fc2f8..1cccaa07c72 100644 --- a/test/utils/update_resources.go +++ b/test/utils/update_resources.go @@ -50,7 +50,7 @@ func ScaleResourceWithRetries(scalesGetter scaleclient.ScalesGetter, namespace, ResourceVersion: "", } waitForReplicas := scale.NewRetryParams(waitRetryInterval, waitRetryTimeout) - cond := RetryErrorCondition(scale.ScaleCondition(scaler, preconditions, namespace, name, size, nil, gvr, false)) + cond := RetryErrorCondition(scale.ScaleCondition(scaler, preconditions, namespace, name, size, nil, nil, gvr, false)) err := wait.PollUntilContextTimeout(context.Background(), updateRetryInterval, updateRetryTimeout, true, cond) if err == nil { err = scale.WaitForScaleHasDesiredReplicas(scalesGetter, gvr.GroupResource(), name, namespace, size, waitForReplicas)