diff --git a/pkg/controller/deployment/deployment_controller.go b/pkg/controller/deployment/deployment_controller.go index 72a0797e742..1b98031da22 100644 --- a/pkg/controller/deployment/deployment_controller.go +++ b/pkg/controller/deployment/deployment_controller.go @@ -847,7 +847,7 @@ func (dc *DeploymentController) reconcileOldReplicaSets(allRSs []*extensions.Rep return false, fmt.Errorf("could not find available pods: %v", err) } - maxUnavailable, err := intstrutil.GetValueFromIntOrPercent(&deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, deployment.Spec.Replicas) + maxUnavailable, err := intstrutil.GetValueFromIntOrPercent(&deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, deployment.Spec.Replicas, false) if err != nil { return false, err } @@ -948,7 +948,7 @@ func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRSs []*extensions.Re // scaleDownOldReplicaSetsForRollingUpdate scales down old replica sets when deployment strategy is "RollingUpdate". // Need check maxUnavailable to ensure availability func (dc *DeploymentController) scaleDownOldReplicaSetsForRollingUpdate(allRSs []*extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet, deployment extensions.Deployment) (int, error) { - maxUnavailable, err := intstrutil.GetValueFromIntOrPercent(&deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, deployment.Spec.Replicas) + maxUnavailable, err := intstrutil.GetValueFromIntOrPercent(&deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, deployment.Spec.Replicas, false) if err != nil { return 0, err } diff --git a/pkg/util/deployment/deployment.go b/pkg/util/deployment/deployment.go index 31aec75b5ff..5649cc9989f 100644 --- a/pkg/util/deployment/deployment.go +++ b/pkg/util/deployment/deployment.go @@ -435,7 +435,7 @@ func NewRSNewReplicas(deployment *extensions.Deployment, allRSs []*extensions.Re switch deployment.Spec.Strategy.Type { case extensions.RollingUpdateDeploymentStrategyType: // Check if we can scale up. - maxSurge, err := intstrutil.GetValueFromIntOrPercent(&deployment.Spec.Strategy.RollingUpdate.MaxSurge, deployment.Spec.Replicas) + maxSurge, err := intstrutil.GetValueFromIntOrPercent(&deployment.Spec.Strategy.RollingUpdate.MaxSurge, deployment.Spec.Replicas, true) if err != nil { return 0, err } diff --git a/pkg/util/intstr/intstr.go b/pkg/util/intstr/intstr.go index 05b572cf5a1..aa3cde1fa87 100644 --- a/pkg/util/intstr/intstr.go +++ b/pkg/util/intstr/intstr.go @@ -116,13 +116,17 @@ func (intstr *IntOrString) Fuzz(c fuzz.Continue) { } } -func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int) (int, error) { +func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool) (int, error) { value, isPercent, err := getIntOrPercentValue(intOrPercent) if err != nil { return 0, fmt.Errorf("invalid value for IntOrString: %v", err) } if isPercent { - value = int(math.Ceil(float64(value) * (float64(total)) / 100)) + if roundUp { + value = int(math.Ceil(float64(value) * (float64(total)) / 100)) + } else { + value = int(math.Floor(float64(value) * (float64(total)) / 100)) + } } return value, nil } diff --git a/pkg/util/intstr/intstr_test.go b/pkg/util/intstr/intstr_test.go index fb36f9d6634..d4ccb6d286b 100644 --- a/pkg/util/intstr/intstr_test.go +++ b/pkg/util/intstr/intstr_test.go @@ -114,6 +114,7 @@ func TestGetValueFromIntOrPercent(t *testing.T) { tests := []struct { input IntOrString total int + roundUp bool expectErr bool expectVal int }{ @@ -125,9 +126,24 @@ func TestGetValueFromIntOrPercent(t *testing.T) { { input: FromString("90%"), total: 100, + roundUp: true, expectErr: false, expectVal: 90, }, + { + input: FromString("90%"), + total: 95, + roundUp: true, + expectErr: false, + expectVal: 86, + }, + { + input: FromString("90%"), + total: 95, + roundUp: false, + expectErr: false, + expectVal: 85, + }, { input: FromString("%"), expectErr: true, @@ -144,7 +160,7 @@ func TestGetValueFromIntOrPercent(t *testing.T) { for i, test := range tests { t.Logf("test case %d", i) - value, err := GetValueFromIntOrPercent(&test.input, test.total) + value, err := GetValueFromIntOrPercent(&test.input, test.total, test.roundUp) if test.expectErr && err == nil { t.Errorf("expected error, but got none") continue @@ -154,7 +170,7 @@ func TestGetValueFromIntOrPercent(t *testing.T) { continue } if test.expectVal != value { - t.Errorf("expected %v, but got %v", test.expectErr, value) + t.Errorf("expected %v, but got %v", test.expectVal, value) } } }