diff --git a/pkg/controller/deployment/deployment_controller.go b/pkg/controller/deployment/deployment_controller.go index 91c308c50e6..7b3d2eab03b 100644 --- a/pkg/controller/deployment/deployment_controller.go +++ b/pkg/controller/deployment/deployment_controller.go @@ -18,7 +18,6 @@ package deployment import ( "fmt" - "math" "reflect" "sort" "strconv" @@ -39,6 +38,7 @@ import ( "k8s.io/kubernetes/pkg/util" deploymentutil "k8s.io/kubernetes/pkg/util/deployment" utilerrors "k8s.io/kubernetes/pkg/util/errors" + "k8s.io/kubernetes/pkg/util/integer" labelsutil "k8s.io/kubernetes/pkg/util/labels" podutil "k8s.io/kubernetes/pkg/util/pod" utilruntime "k8s.io/kubernetes/pkg/util/runtime" @@ -785,7 +785,7 @@ func (dc *DeploymentController) reconcileNewReplicaSet(allRSs []*extensions.Repl // Scale up. scaleUpCount := maxTotalPods - currentPodCount // Do not exceed the number of desired replicas. - scaleUpCount = int(math.Min(float64(scaleUpCount), float64(deployment.Spec.Replicas-newRS.Spec.Replicas))) + scaleUpCount = integer.IntMin(scaleUpCount, deployment.Spec.Replicas-newRS.Spec.Replicas) newReplicasCount := newRS.Spec.Replicas + scaleUpCount _, err = dc.scaleReplicaSetAndRecordEvent(newRS, newReplicasCount, deployment) return true, err @@ -906,7 +906,7 @@ func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRSs []*extensions.Re continue } - scaledDownCount := int(math.Min(float64(maxCleanupCount-totalScaledDown), float64(targetRS.Spec.Replicas-readyPodCount))) + scaledDownCount := integer.IntMin(maxCleanupCount-totalScaledDown, targetRS.Spec.Replicas-readyPodCount) newReplicasCount := targetRS.Spec.Replicas - scaledDownCount _, err = dc.scaleReplicaSetAndRecordEvent(targetRS, newReplicasCount, deployment) if err != nil { @@ -954,7 +954,7 @@ func (dc *DeploymentController) scaleDownOldReplicaSetsForRollingUpdate(allRSs [ continue } // Scale down. - scaleDownCount := int(math.Min(float64(targetRS.Spec.Replicas), float64(totalScaleDownCount-totalScaledDown))) + scaleDownCount := integer.IntMin(targetRS.Spec.Replicas, totalScaleDownCount-totalScaledDown) newReplicasCount := targetRS.Spec.Replicas - scaleDownCount _, err = dc.scaleReplicaSetAndRecordEvent(targetRS, newReplicasCount, deployment) if err != nil { diff --git a/pkg/kubectl/rolling_updater.go b/pkg/kubectl/rolling_updater.go index 7571d96bdea..d734b153dcc 100644 --- a/pkg/kubectl/rolling_updater.go +++ b/pkg/kubectl/rolling_updater.go @@ -30,6 +30,7 @@ import ( client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/util/integer" "k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/wait" ) @@ -214,7 +215,7 @@ func (r *RollingUpdater) Update(config *RollingUpdaterConfig) error { } // The minumum pods which must remain available througout the update // calculated for internal convenience. - minAvailable := int(math.Max(float64(0), float64(desired-maxUnavailable))) + minAvailable := integer.IntMax(0, desired-maxUnavailable) // If the desired new scale is 0, then the max unavailable is necessarily // the effective scale of the old RC regardless of the configuration // (equivalent to 100% maxUnavailable). diff --git a/pkg/util/backoff.go b/pkg/util/backoff.go index 4554ee6a545..0ac526ec953 100644 --- a/pkg/util/backoff.go +++ b/pkg/util/backoff.go @@ -17,9 +17,10 @@ limitations under the License. package util import ( - "math" "sync" "time" + + "k8s.io/kubernetes/pkg/util/integer" ) type backoffEntry struct { @@ -65,7 +66,7 @@ func (p *Backoff) Next(id string, eventTime time.Time) { entry = p.initEntryUnsafe(id) } else { delay := entry.backoff * 2 // exponential - entry.backoff = time.Duration(math.Min(float64(delay), float64(p.maxDuration))) + entry.backoff = time.Duration(integer.Int64Min(int64(delay), int64(p.maxDuration))) } entry.lastUpdate = p.Clock.Now() } diff --git a/pkg/util/integer/integer.go b/pkg/util/integer/integer.go new file mode 100644 index 00000000000..c51cd952d1d --- /dev/null +++ b/pkg/util/integer/integer.go @@ -0,0 +1,45 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 integer + +func IntMax(a, b int) int { + if b > a { + return b + } + return a +} + +func IntMin(a, b int) int { + if b < a { + return b + } + return a +} + +func Int64Max(a, b int64) int64 { + if b > a { + return b + } + return a +} + +func Int64Min(a, b int64) int64 { + if b < a { + return b + } + return a +} diff --git a/pkg/util/integer/integer_test.go b/pkg/util/integer/integer_test.go new file mode 100644 index 00000000000..0f885673827 --- /dev/null +++ b/pkg/util/integer/integer_test.go @@ -0,0 +1,143 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 integer + +import "testing" + +func TestIntMax(t *testing.T) { + tests := []struct { + nums []int + expectedMax int + }{ + { + nums: []int{-1, 0}, + expectedMax: 0, + }, + { + nums: []int{-1, -2}, + expectedMax: -1, + }, + { + nums: []int{0, 1}, + expectedMax: 1, + }, + { + nums: []int{1, 2}, + expectedMax: 2, + }, + } + + for i, test := range tests { + t.Logf("executing scenario %d", i) + if max := IntMax(test.nums[0], test.nums[1]); max != test.expectedMax { + t.Errorf("expected %v, got %v", test.expectedMax, max) + } + } +} + +func TestIntMin(t *testing.T) { + tests := []struct { + nums []int + expectedMin int + }{ + { + nums: []int{-1, 0}, + expectedMin: -1, + }, + { + nums: []int{-1, -2}, + expectedMin: -2, + }, + { + nums: []int{0, 1}, + expectedMin: 0, + }, + { + nums: []int{1, 2}, + expectedMin: 1, + }, + } + + for i, test := range tests { + t.Logf("executing scenario %d", i) + if min := IntMin(test.nums[0], test.nums[1]); min != test.expectedMin { + t.Errorf("expected %v, got %v", test.expectedMin, min) + } + } +} + +func TestInt64Max(t *testing.T) { + tests := []struct { + nums []int64 + expectedMax int64 + }{ + { + nums: []int64{-1, 0}, + expectedMax: 0, + }, + { + nums: []int64{-1, -2}, + expectedMax: -1, + }, + { + nums: []int64{0, 1}, + expectedMax: 1, + }, + { + nums: []int64{1, 2}, + expectedMax: 2, + }, + } + + for i, test := range tests { + t.Logf("executing scenario %d", i) + if max := Int64Max(test.nums[0], test.nums[1]); max != test.expectedMax { + t.Errorf("expected %v, got %v", test.expectedMax, max) + } + } +} + +func TestInt64Min(t *testing.T) { + tests := []struct { + nums []int64 + expectedMin int64 + }{ + { + nums: []int64{-1, 0}, + expectedMin: -1, + }, + { + nums: []int64{-1, -2}, + expectedMin: -2, + }, + { + nums: []int64{0, 1}, + expectedMin: 0, + }, + { + nums: []int64{1, 2}, + expectedMin: 1, + }, + } + + for i, test := range tests { + t.Logf("executing scenario %d", i) + if min := Int64Min(test.nums[0], test.nums[1]); min != test.expectedMin { + t.Errorf("expected %v, got %v", test.expectedMin, min) + } + } +}