Merge pull request #21957 from mqliang/deployment-preserve-availability

Deployment: preserve availability when maxUnavailability is not 100%
This commit is contained in:
Brian Grant 2016-02-24 22:09:54 -08:00
commit b27edde38d
4 changed files with 27 additions and 7 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}
}