mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Merge pull request #25243 from smarterclayton/explore_quantity
Provide an int64 version of Quantity that is much faster
This commit is contained in:
commit
5448400b1c
@ -927,10 +927,10 @@ func parseResourceList(m utilconfig.ConfigurationMap) (api.ResourceList, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if q.Amount.Sign() == -1 {
|
||||
if q.Sign() == -1 {
|
||||
return nil, fmt.Errorf("resource quantity for %q cannot be negative: %v", k, v)
|
||||
}
|
||||
rl[api.ResourceName(k)] = *q
|
||||
rl[api.ResourceName(k)] = q
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot reserve %q resource", k)
|
||||
}
|
||||
|
@ -85,14 +85,8 @@ func podResources(pod *api.Pod, resourceName api.ResourceName, def, min resource
|
||||
}
|
||||
|
||||
// add up the request and limit sum for all containers
|
||||
err = requestSum.Add(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = limitSum.Add(limit)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
requestSum.Add(request)
|
||||
limitSum.Add(limit)
|
||||
|
||||
// optionally write request and limit back
|
||||
if write {
|
||||
|
@ -25,11 +25,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg4_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg1_api "k8s.io/kubernetes/pkg/api"
|
||||
pkg3_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg2_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg5_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg4_types "k8s.io/kubernetes/pkg/types"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -65,13 +64,12 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg4_inf_v0.Dec
|
||||
var v1 pkg1_api.ConditionStatus
|
||||
var v2 pkg3_resource.Quantity
|
||||
var v3 pkg2_unversioned.Time
|
||||
var v4 pkg5_types.UID
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
var v0 pkg1_api.ConditionStatus
|
||||
var v1 pkg3_resource.Quantity
|
||||
var v2 pkg2_unversioned.Time
|
||||
var v3 pkg4_types.UID
|
||||
var v4 time.Time
|
||||
_, _, _, _, _ = v0, v1, v2, v3, v4
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,11 +25,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg4_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg3_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg2_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg1_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
pkg5_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg4_types "k8s.io/kubernetes/pkg/types"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -65,13 +64,12 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg4_inf_v0.Dec
|
||||
var v1 pkg3_resource.Quantity
|
||||
var v2 pkg2_unversioned.Time
|
||||
var v3 pkg1_v1.ConditionStatus
|
||||
var v4 pkg5_types.UID
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
var v0 pkg3_resource.Quantity
|
||||
var v1 pkg2_unversioned.Time
|
||||
var v2 pkg1_v1.ConditionStatus
|
||||
var v3 pkg4_types.UID
|
||||
var v4 time.Time
|
||||
_, _, _, _, _ = v0, v1, v2, v3, v4
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ else
|
||||
linux/amd64
|
||||
linux/arm
|
||||
linux/arm64
|
||||
linux/ppc64le
|
||||
#linux/ppc64le # temporarily disabled due to a linking error
|
||||
)
|
||||
|
||||
# If we update this we should also update the set of golang compilers we build
|
||||
@ -78,7 +78,7 @@ else
|
||||
linux/386
|
||||
linux/arm
|
||||
linux/arm64
|
||||
linux/ppc64le
|
||||
#linux/ppc64le # temporarily disabled due to a linking error
|
||||
darwin/amd64
|
||||
darwin/386
|
||||
windows/amd64
|
||||
|
@ -58,16 +58,7 @@ var Semantic = conversion.EqualitiesOrDie(
|
||||
// TODO: if we decide it's important, it should be safe to start comparing the format.
|
||||
//
|
||||
// Uninitialized quantities are equivalent to 0 quantities.
|
||||
if a.Amount == nil && b.MilliValue() == 0 {
|
||||
return true
|
||||
}
|
||||
if b.Amount == nil && a.MilliValue() == 0 {
|
||||
return true
|
||||
}
|
||||
if a.Amount == nil || b.Amount == nil {
|
||||
return false
|
||||
}
|
||||
return a.Amount.Cmp(b.Amount) == 0
|
||||
return a.Cmp(b) == 0
|
||||
},
|
||||
func(a, b unversioned.Time) bool {
|
||||
return a.UTC() == b.UTC()
|
||||
|
@ -23,8 +23,6 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
|
||||
inf "gopkg.in/inf.v0"
|
||||
)
|
||||
|
||||
func TestConversionError(t *testing.T) {
|
||||
@ -56,8 +54,8 @@ func TestSemantic(t *testing.T) {
|
||||
{resource.Quantity{}, resource.MustParse("0"), true},
|
||||
{resource.Quantity{}, resource.MustParse("1m"), false},
|
||||
{
|
||||
resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.BinarySI},
|
||||
resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.DecimalSI},
|
||||
resource.NewQuantity(5, resource.BinarySI),
|
||||
resource.NewQuantity(5, resource.DecimalSI),
|
||||
true,
|
||||
},
|
||||
{resource.MustParse("2m"), resource.MustParse("1m"), false},
|
||||
|
298
pkg/api/resource/amount.go
Normal file
298
pkg/api/resource/amount.go
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
Copyright 2014 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 resource
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
inf "gopkg.in/inf.v0"
|
||||
)
|
||||
|
||||
// Scale is used for getting and setting the base-10 scaled value.
|
||||
// Base-2 scales are omitted for mathematical simplicity.
|
||||
// See Quantity.ScaledValue for more details.
|
||||
type Scale int32
|
||||
|
||||
// infScale adapts a Scale value to an inf.Scale value.
|
||||
func (s Scale) infScale() inf.Scale {
|
||||
return inf.Scale(-s) // inf.Scale is upside-down
|
||||
}
|
||||
|
||||
const (
|
||||
Nano Scale = -9
|
||||
Micro Scale = -6
|
||||
Milli Scale = -3
|
||||
Kilo Scale = 3
|
||||
Mega Scale = 6
|
||||
Giga Scale = 9
|
||||
Tera Scale = 12
|
||||
Peta Scale = 15
|
||||
Exa Scale = 18
|
||||
)
|
||||
|
||||
var (
|
||||
Zero = int64Amount{}
|
||||
|
||||
// Used by quantity strings - treat as read only
|
||||
zeroBytes = []byte("0")
|
||||
)
|
||||
|
||||
// int64Amount represents a fixed precision numerator and arbitary scale exponent. It is faster
|
||||
// than operations on inf.Dec for values that can be represented as int64.
|
||||
type int64Amount struct {
|
||||
value int64
|
||||
scale Scale
|
||||
}
|
||||
|
||||
// Sign returns 0 if the value is zero, -1 if it is less than 0, or 1 if it is greater than 0.
|
||||
func (a int64Amount) Sign() int {
|
||||
switch {
|
||||
case a.value == 0:
|
||||
return 0
|
||||
case a.value > 0:
|
||||
return 1
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// AsInt64 returns the current amount as an int64 at scale 0, or false if the value cannot be
|
||||
// represented in an int64 OR would result in a loss of precision. This method is intended as
|
||||
// an optimization to avoid calling AsDec.
|
||||
func (a int64Amount) AsInt64() (int64, bool) {
|
||||
if a.scale == 0 {
|
||||
return a.value, true
|
||||
}
|
||||
if a.scale < 0 {
|
||||
// TODO: attempt to reduce factors, although it is assumed that factors are reduced prior
|
||||
// to the int64Amount being created.
|
||||
return 0, false
|
||||
}
|
||||
return positiveScaleInt64(a.value, a.scale)
|
||||
}
|
||||
|
||||
// AsScaledInt64 returns an int64 representing the value of this amount at the specified scale,
|
||||
// rounding up, or false if that would result in overflow. (1e20).AsScaledInt64(1) would result
|
||||
// in overflow because 1e19 is not representable as an int64. Note that setting a scale larger
|
||||
// than the current value may result in loss of precision - i.e. (1e-6).AsScaledInt64(0) would
|
||||
// return 1, because 0.000001 is rounded up to 1.
|
||||
func (a int64Amount) AsScaledInt64(scale Scale) (result int64, ok bool) {
|
||||
if a.scale < scale {
|
||||
result, _ = negativeScaleInt64(a.value, scale-a.scale)
|
||||
return result, true
|
||||
}
|
||||
return positiveScaleInt64(a.value, a.scale-scale)
|
||||
}
|
||||
|
||||
// AsDec returns an inf.Dec representation of this value.
|
||||
func (a int64Amount) AsDec() *inf.Dec {
|
||||
var base inf.Dec
|
||||
base.SetUnscaled(a.value)
|
||||
base.SetScale(inf.Scale(-a.scale))
|
||||
return &base
|
||||
}
|
||||
|
||||
// Cmp returns 0 if a and b are equal, 1 if a is greater than b, or -1 if a is less than b.
|
||||
func (a int64Amount) Cmp(b int64Amount) int {
|
||||
switch {
|
||||
case a.scale == b.scale:
|
||||
// compare only the unscaled portion
|
||||
case a.scale > b.scale:
|
||||
result, remainder, exact := divideByScaleInt64(b.value, a.scale-b.scale)
|
||||
if !exact {
|
||||
return a.AsDec().Cmp(b.AsDec())
|
||||
}
|
||||
if result == a.value {
|
||||
switch {
|
||||
case remainder == 0:
|
||||
return 0
|
||||
case remainder > 0:
|
||||
return -1
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
b.value = result
|
||||
default:
|
||||
result, remainder, exact := divideByScaleInt64(a.value, b.scale-a.scale)
|
||||
if !exact {
|
||||
return a.AsDec().Cmp(b.AsDec())
|
||||
}
|
||||
if result == b.value {
|
||||
switch {
|
||||
case remainder == 0:
|
||||
return 0
|
||||
case remainder > 0:
|
||||
return 1
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
a.value = result
|
||||
}
|
||||
|
||||
switch {
|
||||
case a.value == b.value:
|
||||
return 0
|
||||
case a.value < b.value:
|
||||
return -1
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds two int64Amounts together, matching scales. It will return false and not mutate
|
||||
// a if overflow or underflow would result.
|
||||
func (a *int64Amount) Add(b int64Amount) bool {
|
||||
switch {
|
||||
case b.value == 0:
|
||||
return true
|
||||
case a.value == 0:
|
||||
a.value = b.value
|
||||
a.scale = b.scale
|
||||
return true
|
||||
case a.scale == b.scale:
|
||||
c, ok := int64Add(a.value, b.value)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
a.value = c
|
||||
case a.scale > b.scale:
|
||||
c, ok := positiveScaleInt64(a.value, a.scale-b.scale)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
c, ok = int64Add(c, b.value)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
a.scale = b.scale
|
||||
a.value = c
|
||||
default:
|
||||
c, ok := positiveScaleInt64(b.value, b.scale-a.scale)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
c, ok = int64Add(a.value, c)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
a.value = c
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Sub removes the value of b from the current amount, or returns false if underflow would result.
|
||||
func (a *int64Amount) Sub(b int64Amount) bool {
|
||||
return a.Add(int64Amount{value: -b.value, scale: b.scale})
|
||||
}
|
||||
|
||||
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
|
||||
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
|
||||
func (a int64Amount) AsScale(scale Scale) (int64Amount, bool) {
|
||||
if a.scale >= scale {
|
||||
return a, true
|
||||
}
|
||||
result, exact := negativeScaleInt64(a.value, scale-a.scale)
|
||||
return int64Amount{value: result, scale: scale}, exact
|
||||
}
|
||||
|
||||
// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
|
||||
// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
|
||||
// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
|
||||
func (a int64Amount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
|
||||
mantissa := a.value
|
||||
exponent = int32(a.scale)
|
||||
|
||||
amount, times := removeInt64Factors(mantissa, 10)
|
||||
exponent += int32(times)
|
||||
|
||||
// make sure exponent is a multiple of 3
|
||||
var ok bool
|
||||
switch exponent % 3 {
|
||||
case 1, -2:
|
||||
amount, ok = int64MultiplyScale10(amount)
|
||||
if !ok {
|
||||
return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
|
||||
}
|
||||
exponent = exponent - 1
|
||||
case 2, -1:
|
||||
amount, ok = int64MultiplyScale100(amount)
|
||||
if !ok {
|
||||
return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
|
||||
}
|
||||
exponent = exponent - 2
|
||||
}
|
||||
return strconv.AppendInt(out, amount, 10), exponent
|
||||
}
|
||||
|
||||
// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
|
||||
// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
|
||||
// return []byte("2048"), 1.
|
||||
func (a int64Amount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
|
||||
value, ok := a.AsScaledInt64(0)
|
||||
if !ok {
|
||||
return infDecAmount{a.AsDec()}.AsCanonicalBase1024Bytes(out)
|
||||
}
|
||||
amount, exponent := removeInt64Factors(value, 1024)
|
||||
return strconv.AppendInt(out, amount, 10), exponent
|
||||
}
|
||||
|
||||
// infDecAmount implements common operations over an inf.Dec that are specific to the quantity
|
||||
// representation.
|
||||
type infDecAmount struct {
|
||||
*inf.Dec
|
||||
}
|
||||
|
||||
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
|
||||
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
|
||||
func (a infDecAmount) AsScale(scale Scale) (infDecAmount, bool) {
|
||||
tmp := &inf.Dec{}
|
||||
tmp.Round(a.Dec, scale.infScale(), inf.RoundUp)
|
||||
return infDecAmount{tmp}, tmp.Cmp(a.Dec) == 0
|
||||
}
|
||||
|
||||
// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
|
||||
// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
|
||||
// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
|
||||
func (a infDecAmount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
|
||||
mantissa := a.Dec.UnscaledBig()
|
||||
exponent = int32(-a.Dec.Scale())
|
||||
amount := big.NewInt(0).Set(mantissa)
|
||||
// move all factors of 10 into the exponent for easy reasoning
|
||||
amount, times := removeBigIntFactors(amount, bigTen)
|
||||
exponent += times
|
||||
|
||||
// make sure exponent is a multiple of 3
|
||||
for exponent%3 != 0 {
|
||||
amount.Mul(amount, bigTen)
|
||||
exponent--
|
||||
}
|
||||
|
||||
return append(out, amount.String()...), exponent
|
||||
}
|
||||
|
||||
// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
|
||||
// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
|
||||
// return []byte("2048"), 1.
|
||||
func (a infDecAmount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
|
||||
tmp := &inf.Dec{}
|
||||
tmp.Round(a.Dec, 0, inf.RoundUp)
|
||||
amount, exponent := removeBigIntFactors(tmp.UnscaledBig(), big1024)
|
||||
return append(out, amount.String()...), exponent
|
||||
}
|
111
pkg/api/resource/amount_test.go
Normal file
111
pkg/api/resource/amount_test.go
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2014 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 resource
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInt64AmountAsInt64(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
value int64
|
||||
scale Scale
|
||||
result int64
|
||||
ok bool
|
||||
}{
|
||||
{100, 0, 100, true},
|
||||
{100, 1, 1000, true},
|
||||
{100, -5, 0, false},
|
||||
{100, 100, 0, false},
|
||||
} {
|
||||
r, ok := int64Amount{value: test.value, scale: test.scale}.AsInt64()
|
||||
if r != test.result {
|
||||
t.Errorf("%v: unexpected result: %d", test, r)
|
||||
}
|
||||
if ok != test.ok {
|
||||
t.Errorf("%v: unexpected ok: %t", test, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt64AmountAdd(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
a, b, c int64Amount
|
||||
ok bool
|
||||
}{
|
||||
{int64Amount{value: 100, scale: 1}, int64Amount{value: 10, scale: 2}, int64Amount{value: 200, scale: 1}, true},
|
||||
{int64Amount{value: 100, scale: 1}, int64Amount{value: 1, scale: 2}, int64Amount{value: 110, scale: 1}, true},
|
||||
{int64Amount{value: 100, scale: 1}, int64Amount{value: 1, scale: 100}, int64Amount{value: 1, scale: 100}, false},
|
||||
{int64Amount{value: -5, scale: 2}, int64Amount{value: 50, scale: 1}, int64Amount{value: 0, scale: 1}, true},
|
||||
{int64Amount{value: -5, scale: 2}, int64Amount{value: 5, scale: 2}, int64Amount{value: 0, scale: 2}, true},
|
||||
|
||||
{int64Amount{value: mostPositive, scale: -1}, int64Amount{value: 1, scale: -1}, int64Amount{value: 0, scale: -1}, false},
|
||||
{int64Amount{value: mostPositive, scale: -1}, int64Amount{value: 0, scale: -1}, int64Amount{value: mostPositive, scale: -1}, true},
|
||||
{int64Amount{value: mostPositive / 10, scale: 1}, int64Amount{value: 10, scale: 0}, int64Amount{value: mostPositive, scale: -1}, false},
|
||||
} {
|
||||
c := test.a
|
||||
ok := c.Add(test.b)
|
||||
if ok != test.ok {
|
||||
t.Errorf("%v: unexpected ok: %t", test, ok)
|
||||
}
|
||||
if ok {
|
||||
if c != test.c {
|
||||
t.Errorf("%v: unexpected result: %d", test, c)
|
||||
}
|
||||
} else {
|
||||
if c != test.a {
|
||||
t.Errorf("%v: overflow addition mutated source: %d", test, c)
|
||||
}
|
||||
}
|
||||
|
||||
// addition is commutative
|
||||
c = test.b
|
||||
if ok := c.Add(test.a); ok != test.ok {
|
||||
t.Errorf("%v: unexpected ok: %t", test, ok)
|
||||
}
|
||||
if ok {
|
||||
if c != test.c {
|
||||
t.Errorf("%v: unexpected result: %d", test, c)
|
||||
}
|
||||
} else {
|
||||
if c != test.b {
|
||||
t.Errorf("%v: overflow addition mutated source: %d", test, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestInt64AsCanonicalString(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
value int64
|
||||
scale Scale
|
||||
result string
|
||||
exponent int32
|
||||
}{
|
||||
{100, 0, "100", 0},
|
||||
{100, 1, "1", 3},
|
||||
{100, -1, "10", 0},
|
||||
{10800, -10, "1080", -9},
|
||||
} {
|
||||
r, exp := int64Amount{value: test.value, scale: test.scale}.AsCanonicalBytes(nil)
|
||||
if string(r) != test.result {
|
||||
t.Errorf("%v: unexpected result: %s", test, r)
|
||||
}
|
||||
if exp != test.exponent {
|
||||
t.Errorf("%v: unexpected exponent: %d", test, exp)
|
||||
}
|
||||
}
|
||||
}
|
@ -21,35 +21,27 @@ limitations under the License.
|
||||
package resource
|
||||
|
||||
import (
|
||||
inf_v0 "gopkg.in/inf.v0"
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func DeepCopy_resource_Quantity(in Quantity, out *Quantity, c *conversion.Cloner) error {
|
||||
if in.Amount != nil {
|
||||
in, out := in.Amount, &out.Amount
|
||||
*out = new(inf_v0.Dec)
|
||||
if newVal, err := c.DeepCopy(*in); err != nil {
|
||||
if newVal, err := c.DeepCopy(in.i); err != nil {
|
||||
return err
|
||||
} else {
|
||||
**out = newVal.(inf_v0.Dec)
|
||||
out.i = newVal.(int64Amount)
|
||||
}
|
||||
if newVal, err := c.DeepCopy(in.d); err != nil {
|
||||
return err
|
||||
} else {
|
||||
out.Amount = nil
|
||||
out.d = newVal.(infDecAmount)
|
||||
}
|
||||
out.Format = in.Format
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_resource_QuantityProto(in QuantityProto, out *QuantityProto, c *conversion.Cloner) error {
|
||||
out.Format = in.Format
|
||||
out.Scale = in.Scale
|
||||
if in.Bigint != nil {
|
||||
in, out := in.Bigint, &out.Bigint
|
||||
if in.s != nil {
|
||||
in, out := in.s, &out.s
|
||||
*out = make([]byte, len(in))
|
||||
copy(*out, in)
|
||||
} else {
|
||||
out.Bigint = nil
|
||||
out.s = nil
|
||||
}
|
||||
out.Format = in.Format
|
||||
return nil
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ limitations under the License.
|
||||
|
||||
It has these top-level messages:
|
||||
Quantity
|
||||
QuantityProto
|
||||
*/
|
||||
package resource
|
||||
|
||||
@ -34,8 +33,6 @@ import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
@ -44,328 +41,6 @@ var _ = math.Inf
|
||||
func (m *Quantity) Reset() { *m = Quantity{} }
|
||||
func (*Quantity) ProtoMessage() {}
|
||||
|
||||
func (m *QuantityProto) Reset() { *m = QuantityProto{} }
|
||||
func (m *QuantityProto) String() string { return proto.CompactTextString(m) }
|
||||
func (*QuantityProto) ProtoMessage() {}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Quantity)(nil), "k8s.io.kubernetes.pkg.api.resource.Quantity")
|
||||
proto.RegisterType((*QuantityProto)(nil), "k8s.io.kubernetes.pkg.api.resource.QuantityProto")
|
||||
}
|
||||
func (m *QuantityProto) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *QuantityProto) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(len(m.Format)))
|
||||
i += copy(data[i:], m.Format)
|
||||
data[i] = 0x10
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.Scale))
|
||||
if m.Bigint != nil {
|
||||
data[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(len(m.Bigint)))
|
||||
i += copy(data[i:], m.Bigint)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(data []byte, offset int, v uint64) int {
|
||||
data[offset] = uint8(v)
|
||||
data[offset+1] = uint8(v >> 8)
|
||||
data[offset+2] = uint8(v >> 16)
|
||||
data[offset+3] = uint8(v >> 24)
|
||||
data[offset+4] = uint8(v >> 32)
|
||||
data[offset+5] = uint8(v >> 40)
|
||||
data[offset+6] = uint8(v >> 48)
|
||||
data[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(data []byte, offset int, v uint32) int {
|
||||
data[offset] = uint8(v)
|
||||
data[offset+1] = uint8(v >> 8)
|
||||
data[offset+2] = uint8(v >> 16)
|
||||
data[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(data []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
data[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
data[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *QuantityProto) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Format)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
n += 1 + sovGenerated(uint64(m.Scale))
|
||||
if m.Bigint != nil {
|
||||
l = len(m.Bigint)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *QuantityProto) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: QuantityProto: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: QuantityProto: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Format = Format(data[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Scale", wireType)
|
||||
}
|
||||
m.Scale = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
m.Scale |= (int32(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Bigint", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Bigint = append(m.Bigint[:0], data[iNdEx:postIndex]...)
|
||||
if m.Bigint == nil {
|
||||
m.Bigint = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(data []byte) (n int, err error) {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if data[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(data[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
@ -84,26 +84,10 @@ option go_package = "resource";
|
||||
// cause implementors to also use a fixed point implementation.
|
||||
//
|
||||
// +protobuf=true
|
||||
// +protobuf.embed=QuantityProto
|
||||
// +protobuf.embed=string
|
||||
// +protobuf.options.marshal=false
|
||||
// +protobuf.options.(gogoproto.goproto_stringer)=false
|
||||
message Quantity {
|
||||
optional QuantityProto QuantityProto = 1;
|
||||
}
|
||||
|
||||
// QuantityProto is a struct that is equivalent to Quantity, but intended for
|
||||
// protobuf marshalling/unmarshalling. It is generated into a serialization
|
||||
// that matches Quantity. Do not use in Go structs.
|
||||
//
|
||||
// +protobuf=true
|
||||
message QuantityProto {
|
||||
// The format of the quantity
|
||||
optional string format = 1;
|
||||
|
||||
// The scale dimension of the value
|
||||
optional int32 scale = 2;
|
||||
|
||||
// Bigint is serialized as a raw bytes array
|
||||
optional bytes bigint = 3;
|
||||
optional string string = 1;
|
||||
}
|
||||
|
||||
|
327
pkg/api/resource/math.go
Normal file
327
pkg/api/resource/math.go
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
Copyright 2014 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 resource
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
inf "gopkg.in/inf.v0"
|
||||
)
|
||||
|
||||
const (
|
||||
// maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64.
|
||||
// It is also the maximum decimal digits that can be represented with an int64.
|
||||
maxInt64Factors = 18
|
||||
)
|
||||
|
||||
var (
|
||||
// Commonly needed big.Int values-- treat as read only!
|
||||
bigTen = big.NewInt(10)
|
||||
bigZero = big.NewInt(0)
|
||||
bigOne = big.NewInt(1)
|
||||
bigThousand = big.NewInt(1000)
|
||||
big1024 = big.NewInt(1024)
|
||||
|
||||
// Commonly needed inf.Dec values-- treat as read only!
|
||||
decZero = inf.NewDec(0, 0)
|
||||
decOne = inf.NewDec(1, 0)
|
||||
decMinusOne = inf.NewDec(-1, 0)
|
||||
decThousand = inf.NewDec(1000, 0)
|
||||
dec1024 = inf.NewDec(1024, 0)
|
||||
decMinus1024 = inf.NewDec(-1024, 0)
|
||||
|
||||
// Largest (in magnitude) number allowed.
|
||||
maxAllowed = infDecAmount{inf.NewDec((1<<63)-1, 0)} // == max int64
|
||||
|
||||
// The maximum value we can represent milli-units for.
|
||||
// Compare with the return value of Quantity.Value() to
|
||||
// see if it's safe to use Quantity.MilliValue().
|
||||
MaxMilliValue = int64(((1 << 63) - 1) / 1000)
|
||||
)
|
||||
|
||||
const mostNegative = -(mostPositive + 1)
|
||||
const mostPositive = 1<<63 - 1
|
||||
|
||||
// int64Add returns a+b, or false if that would overflow int64.
|
||||
func int64Add(a, b int64) (int64, bool) {
|
||||
c := a + b
|
||||
switch {
|
||||
case a > 0 && b > 0:
|
||||
if c < 0 {
|
||||
return 0, false
|
||||
}
|
||||
case a < 0 && b < 0:
|
||||
if c > 0 {
|
||||
return 0, false
|
||||
}
|
||||
if a == mostNegative && b == mostNegative {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
return c, true
|
||||
}
|
||||
|
||||
// int64Multiply returns a*b, or false if that would overflow or underflow int64.
|
||||
func int64Multiply(a, b int64) (int64, bool) {
|
||||
if a == 0 || b == 0 || a == 1 || b == 1 {
|
||||
return a * b, true
|
||||
}
|
||||
if a == mostNegative || b == mostNegative {
|
||||
return 0, false
|
||||
}
|
||||
c := a * b
|
||||
return c, c/b == a
|
||||
}
|
||||
|
||||
// int64MultiplyScale returns a*b, assuming b is greater than one, or false if that would overflow or underflow int64.
|
||||
// Use when b is known to be greater than one.
|
||||
func int64MultiplyScale(a int64, b int64) (int64, bool) {
|
||||
if a == 0 || a == 1 {
|
||||
return a * b, true
|
||||
}
|
||||
if a == mostNegative && b != 1 {
|
||||
return 0, false
|
||||
}
|
||||
c := a * b
|
||||
return c, c/b == a
|
||||
}
|
||||
|
||||
// int64MultiplyScale10 multiplies a by 10, or returns false if that would overflow. This method is faster than
|
||||
// int64Multiply(a, 10) because the compiler can optimize constant factor multiplication.
|
||||
func int64MultiplyScale10(a int64) (int64, bool) {
|
||||
if a == 0 || a == 1 {
|
||||
return a * 10, true
|
||||
}
|
||||
if a == mostNegative {
|
||||
return 0, false
|
||||
}
|
||||
c := a * 10
|
||||
return c, c/10 == a
|
||||
}
|
||||
|
||||
// int64MultiplyScale100 multiplies a by 100, or returns false if that would overflow. This method is faster than
|
||||
// int64Multiply(a, 100) because the compiler can optimize constant factor multiplication.
|
||||
func int64MultiplyScale100(a int64) (int64, bool) {
|
||||
if a == 0 || a == 1 {
|
||||
return a * 100, true
|
||||
}
|
||||
if a == mostNegative {
|
||||
return 0, false
|
||||
}
|
||||
c := a * 100
|
||||
return c, c/100 == a
|
||||
}
|
||||
|
||||
// int64MultiplyScale1000 multiplies a by 1000, or returns false if that would overflow. This method is faster than
|
||||
// int64Multiply(a, 1000) because the compiler can optimize constant factor multiplication.
|
||||
func int64MultiplyScale1000(a int64) (int64, bool) {
|
||||
if a == 0 || a == 1 {
|
||||
return a * 1000, true
|
||||
}
|
||||
if a == mostNegative {
|
||||
return 0, false
|
||||
}
|
||||
c := a * 1000
|
||||
return c, c/1000 == a
|
||||
}
|
||||
|
||||
// positiveScaleInt64 multiplies base by 10^scale, returning false if the
|
||||
// value overflows. Passing a negative scale is undefined.
|
||||
func positiveScaleInt64(base int64, scale Scale) (int64, bool) {
|
||||
switch scale {
|
||||
case 0:
|
||||
return base, true
|
||||
case 1:
|
||||
return int64MultiplyScale10(base)
|
||||
case 2:
|
||||
return int64MultiplyScale100(base)
|
||||
case 3:
|
||||
return int64MultiplyScale1000(base)
|
||||
case 6:
|
||||
return int64MultiplyScale(base, 1000000)
|
||||
case 9:
|
||||
return int64MultiplyScale(base, 1000000000)
|
||||
default:
|
||||
value := base
|
||||
var ok bool
|
||||
for i := Scale(0); i < scale; i++ {
|
||||
if value, ok = int64MultiplyScale(value, 10); !ok {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
}
|
||||
|
||||
// negativeScaleInt64 reduces base by the provided scale, rounding up, until the
|
||||
// value is zero or the scale is reached. Passing a negative scale is undefined.
|
||||
// The value returned, if not exact, is rounded away from zero.
|
||||
func negativeScaleInt64(base int64, scale Scale) (result int64, exact bool) {
|
||||
if scale == 0 {
|
||||
return base, true
|
||||
}
|
||||
|
||||
value := base
|
||||
var fraction bool
|
||||
for i := Scale(0); i < scale; i++ {
|
||||
if !fraction && value%10 != 0 {
|
||||
fraction = true
|
||||
}
|
||||
value = value / 10
|
||||
if value == 0 {
|
||||
if fraction {
|
||||
if base > 0 {
|
||||
return 1, false
|
||||
}
|
||||
return -1, false
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
}
|
||||
if fraction {
|
||||
if base > 0 {
|
||||
value += 1
|
||||
} else {
|
||||
value += -1
|
||||
}
|
||||
}
|
||||
return value, !fraction
|
||||
}
|
||||
|
||||
func pow10Int64(b int64) int64 {
|
||||
switch b {
|
||||
case 0:
|
||||
return 1
|
||||
case 1:
|
||||
return 10
|
||||
case 2:
|
||||
return 100
|
||||
case 3:
|
||||
return 1000
|
||||
case 4:
|
||||
return 10000
|
||||
case 5:
|
||||
return 100000
|
||||
case 6:
|
||||
return 1000000
|
||||
case 7:
|
||||
return 10000000
|
||||
case 8:
|
||||
return 100000000
|
||||
case 9:
|
||||
return 1000000000
|
||||
case 10:
|
||||
return 10000000000
|
||||
case 11:
|
||||
return 100000000000
|
||||
case 12:
|
||||
return 1000000000000
|
||||
case 13:
|
||||
return 10000000000000
|
||||
case 14:
|
||||
return 100000000000000
|
||||
case 15:
|
||||
return 1000000000000000
|
||||
case 16:
|
||||
return 10000000000000000
|
||||
case 17:
|
||||
return 100000000000000000
|
||||
case 18:
|
||||
return 1000000000000000000
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// powInt64 raises a to the bth power. Is not overflow aware.
|
||||
func powInt64(a, b int64) int64 {
|
||||
p := int64(1)
|
||||
for b > 0 {
|
||||
if b&1 != 0 {
|
||||
p *= a
|
||||
}
|
||||
b >>= 1
|
||||
a *= a
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// negativeScaleInt64 returns the result of dividing base by scale * 10 and the remainder, or
|
||||
// false if no such division is possible. Dividing by negative scales is undefined.
|
||||
func divideByScaleInt64(base int64, scale Scale) (result, remainder int64, exact bool) {
|
||||
if scale == 0 {
|
||||
return base, 0, true
|
||||
}
|
||||
// the max scale representable in base 10 in an int64 is 18 decimal places
|
||||
if scale >= 18 {
|
||||
return 0, base, false
|
||||
}
|
||||
divisor := pow10Int64(int64(scale))
|
||||
return base / divisor, base % divisor, true
|
||||
}
|
||||
|
||||
// removeInt64Factors divides in a loop; the return values have the property that
|
||||
// value == result * base ^ scale
|
||||
func removeInt64Factors(value int64, base int64) (result int64, times int32) {
|
||||
times = 0
|
||||
result = value
|
||||
negative := result < 0
|
||||
if negative {
|
||||
result = -result
|
||||
}
|
||||
switch base {
|
||||
// allow the compiler to optimize the common cases
|
||||
case 10:
|
||||
for result >= 10 && result%10 == 0 {
|
||||
times++
|
||||
result = result / 10
|
||||
}
|
||||
// allow the compiler to optimize the common cases
|
||||
case 1024:
|
||||
for result >= 1024 && result%1024 == 0 {
|
||||
times++
|
||||
result = result / 1024
|
||||
}
|
||||
default:
|
||||
for result >= base && result%base == 0 {
|
||||
times++
|
||||
result = result / base
|
||||
}
|
||||
}
|
||||
if negative {
|
||||
result = -result
|
||||
}
|
||||
return result, times
|
||||
}
|
||||
|
||||
// removeBigIntFactors divides in a loop; the return values have the property that
|
||||
// d == result * factor ^ times
|
||||
// d may be modified in place.
|
||||
// If d == 0, then the return values will be (0, 0)
|
||||
func removeBigIntFactors(d, factor *big.Int) (result *big.Int, times int32) {
|
||||
q := big.NewInt(0)
|
||||
m := big.NewInt(0)
|
||||
for d.Cmp(bigZero) != 0 {
|
||||
q.DivMod(d, factor, m)
|
||||
if m.Cmp(bigZero) != 0 {
|
||||
break
|
||||
}
|
||||
times++
|
||||
d, q = q, d
|
||||
}
|
||||
return d, times
|
||||
}
|
211
pkg/api/resource/math_test.go
Normal file
211
pkg/api/resource/math_test.go
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright 2014 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 resource
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDetectOverflowAdd(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
a, b int64
|
||||
c int64
|
||||
ok bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{-1, 1, 0, true},
|
||||
{0, 1, 1, true},
|
||||
{2, 2, 4, true},
|
||||
{2, -2, 0, true},
|
||||
{-2, -2, -4, true},
|
||||
|
||||
{mostNegative, -1, 0, false},
|
||||
{mostNegative, 1, mostNegative + 1, true},
|
||||
{mostPositive, -1, mostPositive - 1, true},
|
||||
{mostPositive, 1, 0, false},
|
||||
|
||||
{mostNegative, mostPositive, -1, true},
|
||||
{mostPositive, mostNegative, -1, true},
|
||||
{mostPositive, mostPositive, 0, false},
|
||||
{mostNegative, mostNegative, 0, false},
|
||||
|
||||
{-mostPositive, mostNegative, 0, false},
|
||||
{mostNegative, -mostPositive, 0, false},
|
||||
{-mostPositive, -mostPositive, 0, false},
|
||||
} {
|
||||
c, ok := int64Add(test.a, test.b)
|
||||
if c != test.c {
|
||||
t.Errorf("%v: unexpected result: %d", test, c)
|
||||
}
|
||||
if ok != test.ok {
|
||||
t.Errorf("%v: unexpected overflow: %t", test, ok)
|
||||
}
|
||||
// addition is commutative
|
||||
d, ok2 := int64Add(test.b, test.a)
|
||||
if c != d || ok != ok2 {
|
||||
t.Errorf("%v: not commutative: %d %t", test, d, ok2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectOverflowMultiply(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
a, b int64
|
||||
c int64
|
||||
ok bool
|
||||
}{
|
||||
{0, 0, 0, true},
|
||||
{-1, 1, -1, true},
|
||||
{-1, -1, 1, true},
|
||||
{1, 1, 1, true},
|
||||
{0, 1, 0, true},
|
||||
{1, 0, 0, true},
|
||||
{2, 2, 4, true},
|
||||
{2, -2, -4, true},
|
||||
{-2, -2, 4, true},
|
||||
|
||||
{mostNegative, -1, 0, false},
|
||||
{mostNegative, 1, mostNegative, true},
|
||||
{mostPositive, -1, -mostPositive, true},
|
||||
{mostPositive, 1, mostPositive, true},
|
||||
|
||||
{mostNegative, mostPositive, 0, false},
|
||||
{mostPositive, mostNegative, 0, false},
|
||||
{mostPositive, mostPositive, 1, false},
|
||||
{mostNegative, mostNegative, 0, false},
|
||||
|
||||
{-mostPositive, mostNegative, 0, false},
|
||||
{mostNegative, -mostPositive, 0, false},
|
||||
{-mostPositive, -mostPositive, 1, false},
|
||||
} {
|
||||
c, ok := int64Multiply(test.a, test.b)
|
||||
if c != test.c {
|
||||
t.Errorf("%v: unexpected result: %d", test, c)
|
||||
}
|
||||
if ok != test.ok {
|
||||
t.Errorf("%v: unexpected overflow: %t", test, ok)
|
||||
}
|
||||
// multiplication is commutative
|
||||
d, ok2 := int64Multiply(test.b, test.a)
|
||||
if c != d || ok != ok2 {
|
||||
t.Errorf("%v: not commutative: %d %t", test, d, ok2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectOverflowScale(t *testing.T) {
|
||||
for _, a := range []int64{0, -1, 1, 10, -10, mostPositive, mostNegative, -mostPositive} {
|
||||
for _, b := range []int64{1, 2, 10, 100, 1000, mostPositive} {
|
||||
expect, expectOk := int64Multiply(a, b)
|
||||
|
||||
c, ok := int64MultiplyScale(a, b)
|
||||
if c != expect {
|
||||
t.Errorf("%d*%d: unexpected result: %d", a, b, c)
|
||||
}
|
||||
if ok != expectOk {
|
||||
t.Errorf("%d*%d: unexpected overflow: %t", a, b, ok)
|
||||
}
|
||||
}
|
||||
for _, test := range []struct {
|
||||
base int64
|
||||
fn func(a int64) (int64, bool)
|
||||
}{
|
||||
{10, int64MultiplyScale10},
|
||||
{100, int64MultiplyScale100},
|
||||
{1000, int64MultiplyScale1000},
|
||||
} {
|
||||
expect, expectOk := int64Multiply(a, test.base)
|
||||
c, ok := test.fn(a)
|
||||
if c != expect {
|
||||
t.Errorf("%d*%d: unexpected result: %d", a, test.base, c)
|
||||
}
|
||||
if ok != expectOk {
|
||||
t.Errorf("%d*%d: unexpected overflow: %t", a, test.base, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveInt64Factors(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
value int64
|
||||
max int64
|
||||
result int64
|
||||
scale int32
|
||||
}{
|
||||
{100, 10, 1, 2},
|
||||
{100, 10, 1, 2},
|
||||
{100, 100, 1, 1},
|
||||
{1, 10, 1, 0},
|
||||
} {
|
||||
r, s := removeInt64Factors(test.value, test.max)
|
||||
if r != test.result {
|
||||
t.Errorf("%v: unexpected result: %d", test, r)
|
||||
}
|
||||
if s != test.scale {
|
||||
t.Errorf("%v: unexpected scale: %d", test, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeScaleInt64(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
base int64
|
||||
scale Scale
|
||||
result int64
|
||||
exact bool
|
||||
}{
|
||||
{1234567, 0, 1234567, true},
|
||||
{1234567, 1, 123457, false},
|
||||
{1234567, 2, 12346, false},
|
||||
{1234567, 3, 1235, false},
|
||||
{1234567, 4, 124, false},
|
||||
|
||||
{-1234567, 0, -1234567, true},
|
||||
{-1234567, 1, -123457, false},
|
||||
{-1234567, 2, -12346, false},
|
||||
{-1234567, 3, -1235, false},
|
||||
{-1234567, 4, -124, false},
|
||||
|
||||
{1000, 0, 1000, true},
|
||||
{1000, 1, 100, true},
|
||||
{1000, 2, 10, true},
|
||||
{1000, 3, 1, true},
|
||||
{1000, 4, 1, false},
|
||||
|
||||
{-1000, 0, -1000, true},
|
||||
{-1000, 1, -100, true},
|
||||
{-1000, 2, -10, true},
|
||||
{-1000, 3, -1, true},
|
||||
{-1000, 4, -1, false},
|
||||
|
||||
{0, 0, 0, true},
|
||||
{0, 1, 0, true},
|
||||
{0, 2, 0, true},
|
||||
|
||||
// negative scale is undefined behavior
|
||||
{1000, -1, 1000, true},
|
||||
} {
|
||||
result, exact := negativeScaleInt64(test.base, test.scale)
|
||||
if result != test.result {
|
||||
t.Errorf("%v: unexpected result: %d", test, result)
|
||||
}
|
||||
if exact != test.exact {
|
||||
t.Errorf("%v: unexpected exact: %t", test, exact)
|
||||
}
|
||||
}
|
||||
}
|
@ -17,10 +17,12 @@ limitations under the License.
|
||||
package resource
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
@ -86,19 +88,34 @@ import (
|
||||
// cause implementors to also use a fixed point implementation.
|
||||
//
|
||||
// +protobuf=true
|
||||
// +protobuf.embed=QuantityProto
|
||||
// +protobuf.embed=string
|
||||
// +protobuf.options.marshal=false
|
||||
// +protobuf.options.(gogoproto.goproto_stringer)=false
|
||||
type Quantity struct {
|
||||
// Amount is public, so you can manipulate it if the accessor
|
||||
// functions are not sufficient.
|
||||
Amount *inf.Dec
|
||||
// i is the quantity in int64 scaled form, if d.Dec == nil
|
||||
i int64Amount
|
||||
// d is the quantity in inf.Dec form if d.Dec != nil
|
||||
d infDecAmount
|
||||
// s is the generated value of this quantity to avoid recalculation
|
||||
s []byte
|
||||
|
||||
// Change Format at will. See the comment for Canonicalize for
|
||||
// more details.
|
||||
Format
|
||||
}
|
||||
|
||||
// CanonicalValue allows a quantity amount to be converted to a string.
|
||||
type CanonicalValue interface {
|
||||
// AsCanonicalBytes returns a byte array representing the string representation
|
||||
// of the value mantissa and an int32 representing its exponent in base-10. Callers may
|
||||
// pass a byte slice to the method to avoid allocations.
|
||||
AsCanonicalBytes(out []byte) ([]byte, int32)
|
||||
// AsCanonicalBase1024Bytes returns a byte array representing the string representation
|
||||
// of the value mantissa and an int32 representing its exponent in base-1024. Callers
|
||||
// may pass a byte slice to the method to avoid allocations.
|
||||
AsCanonicalBase1024Bytes(out []byte) ([]byte, int32)
|
||||
}
|
||||
|
||||
// Format lists the three possible formattings of a quantity.
|
||||
type Format string
|
||||
|
||||
@ -115,26 +132,9 @@ func MustParse(str string) Quantity {
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot parse '%v': %v", str, err))
|
||||
}
|
||||
return *q
|
||||
return q
|
||||
}
|
||||
|
||||
// Scale is used for getting and setting the base-10 scaled value.
|
||||
// Base-2 scales are omitted for mathematical simplicity.
|
||||
// See Quantity.ScaledValue for more details.
|
||||
type Scale int
|
||||
|
||||
const (
|
||||
Nano Scale = -9
|
||||
Micro Scale = -6
|
||||
Milli Scale = -3
|
||||
Kilo Scale = 3
|
||||
Mega Scale = 6
|
||||
Giga Scale = 9
|
||||
Tera Scale = 12
|
||||
Peta Scale = 15
|
||||
Exa Scale = 18
|
||||
)
|
||||
|
||||
const (
|
||||
// splitREString is used to separate a number from its suffix; as such,
|
||||
// this is overly permissive, but that's OK-- it will be checked later.
|
||||
@ -149,47 +149,189 @@ var (
|
||||
ErrFormatWrong = errors.New("quantities must match the regular expression '" + splitREString + "'")
|
||||
ErrNumeric = errors.New("unable to parse numeric part of quantity")
|
||||
ErrSuffix = errors.New("unable to parse quantity's suffix")
|
||||
|
||||
// Commonly needed big.Int values-- treat as read only!
|
||||
bigTen = big.NewInt(10)
|
||||
bigZero = big.NewInt(0)
|
||||
bigOne = big.NewInt(1)
|
||||
bigThousand = big.NewInt(1000)
|
||||
big1024 = big.NewInt(1024)
|
||||
|
||||
// Commonly needed inf.Dec values-- treat as read only!
|
||||
decZero = inf.NewDec(0, 0)
|
||||
decOne = inf.NewDec(1, 0)
|
||||
decMinusOne = inf.NewDec(-1, 0)
|
||||
decThousand = inf.NewDec(1000, 0)
|
||||
dec1024 = inf.NewDec(1024, 0)
|
||||
decMinus1024 = inf.NewDec(-1024, 0)
|
||||
|
||||
// Largest (in magnitude) number allowed.
|
||||
maxAllowed = inf.NewDec((1<<63)-1, 0) // == max int64
|
||||
|
||||
// The maximum value we can represent milli-units for.
|
||||
// Compare with the return value of Quantity.Value() to
|
||||
// see if it's safe to use Quantity.MilliValue().
|
||||
MaxMilliValue = int64(((1 << 63) - 1) / 1000)
|
||||
)
|
||||
|
||||
// parseQuantityString is a fast scanner for quantity values.
|
||||
func parseQuantityString(str string) (positive bool, value, num, denom, suffix string, err error) {
|
||||
positive = true
|
||||
pos := 0
|
||||
end := len(str)
|
||||
|
||||
// handle leading sign
|
||||
if pos < end {
|
||||
switch str[0] {
|
||||
case '-':
|
||||
positive = false
|
||||
pos++
|
||||
case '+':
|
||||
pos++
|
||||
}
|
||||
}
|
||||
|
||||
// strip leading zeros
|
||||
Zeroes:
|
||||
for i := pos; ; i++ {
|
||||
if i >= end {
|
||||
num = "0"
|
||||
value = num
|
||||
return
|
||||
}
|
||||
switch str[i] {
|
||||
case '0':
|
||||
pos++
|
||||
default:
|
||||
break Zeroes
|
||||
}
|
||||
}
|
||||
|
||||
// extract the numerator
|
||||
Num:
|
||||
for i := pos; ; i++ {
|
||||
if i >= end {
|
||||
num = str[pos:end]
|
||||
value = str[0:end]
|
||||
return
|
||||
}
|
||||
switch str[i] {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
default:
|
||||
num = str[pos:i]
|
||||
pos = i
|
||||
break Num
|
||||
}
|
||||
}
|
||||
|
||||
// if we stripped all numerator positions, always return 0
|
||||
if len(num) == 0 {
|
||||
num = "0"
|
||||
}
|
||||
|
||||
// handle a denominator
|
||||
if pos < end && str[pos] == '.' {
|
||||
pos++
|
||||
Denom:
|
||||
for i := pos; ; i++ {
|
||||
if i >= end {
|
||||
denom = str[pos:end]
|
||||
value = str[0:end]
|
||||
return
|
||||
}
|
||||
switch str[i] {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
default:
|
||||
denom = str[pos:i]
|
||||
pos = i
|
||||
break Denom
|
||||
}
|
||||
}
|
||||
// TODO: we currently allow 1.G, but we may not want to in the future.
|
||||
// if len(denom) == 0 {
|
||||
// err = ErrFormatWrong
|
||||
// return
|
||||
// }
|
||||
}
|
||||
value = str[0:pos]
|
||||
|
||||
// grab the elements of the suffix
|
||||
suffixStart := pos
|
||||
for i := pos; ; i++ {
|
||||
if i >= end {
|
||||
suffix = str[suffixStart:end]
|
||||
return
|
||||
}
|
||||
if !strings.ContainsAny(str[i:i+1], "eEinumkKMGTP") {
|
||||
pos = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if pos < end {
|
||||
switch str[pos] {
|
||||
case '-', '+':
|
||||
pos++
|
||||
}
|
||||
}
|
||||
Suffix:
|
||||
for i := pos; ; i++ {
|
||||
if i >= end {
|
||||
suffix = str[suffixStart:end]
|
||||
return
|
||||
}
|
||||
switch str[i] {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
default:
|
||||
pos = i
|
||||
break Suffix
|
||||
}
|
||||
}
|
||||
// we encountered a non decimal in the Suffix loop, but the last character
|
||||
// was not a valid exponent
|
||||
err = ErrFormatWrong
|
||||
return
|
||||
}
|
||||
|
||||
// ParseQuantity turns str into a Quantity, or returns an error.
|
||||
func ParseQuantity(str string) (*Quantity, error) {
|
||||
parts := splitRE.FindStringSubmatch(strings.TrimSpace(str))
|
||||
// regexp returns are entire match, followed by an entry for each () section.
|
||||
if len(parts) != 3 {
|
||||
return nil, ErrFormatWrong
|
||||
func ParseQuantity(str string) (Quantity, error) {
|
||||
if len(str) == 0 {
|
||||
return Quantity{}, ErrFormatWrong
|
||||
}
|
||||
if str == "0" {
|
||||
return Quantity{Format: DecimalSI}, nil
|
||||
}
|
||||
|
||||
positive, value, num, denom, suf, err := parseQuantityString(str)
|
||||
if err != nil {
|
||||
return Quantity{}, err
|
||||
}
|
||||
|
||||
base, exponent, format, ok := quantitySuffixer.interpret(suffix(suf))
|
||||
if !ok {
|
||||
return Quantity{}, ErrSuffix
|
||||
}
|
||||
|
||||
precision := int32(0)
|
||||
scale := int32(0)
|
||||
mantissa := int64(1)
|
||||
switch format {
|
||||
case DecimalExponent, DecimalSI:
|
||||
scale = exponent
|
||||
precision = maxInt64Factors - int32(len(num)+len(denom))
|
||||
case BinarySI:
|
||||
scale = 0
|
||||
switch {
|
||||
case exponent >= 0 && len(denom) == 0:
|
||||
// only handle positive binary numbers with the fast path
|
||||
mantissa = int64(int64(mantissa) << uint64(exponent))
|
||||
// 1Mi (2^20) has ~6 digits of decimal precision, so exponent*3/10 -1 is roughly the precision
|
||||
precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1
|
||||
default:
|
||||
precision = -1
|
||||
}
|
||||
}
|
||||
|
||||
if precision >= 0 {
|
||||
// if we have a denominator, shift the entire value to the left by the number of places in the
|
||||
// denominator
|
||||
scale -= int32(len(denom))
|
||||
if scale >= int32(Nano) {
|
||||
shifted := num + denom
|
||||
|
||||
var value int64
|
||||
value, err := strconv.ParseInt(shifted, 10, 64)
|
||||
if err != nil {
|
||||
return Quantity{}, ErrNumeric
|
||||
}
|
||||
if result, ok := int64Multiply(value, int64(mantissa)); ok {
|
||||
if !positive {
|
||||
result = -result
|
||||
}
|
||||
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amount := new(inf.Dec)
|
||||
if _, ok := amount.SetString(parts[1]); !ok {
|
||||
return nil, ErrNumeric
|
||||
}
|
||||
|
||||
base, exponent, format, ok := quantitySuffixer.interpret(suffix(parts[2]))
|
||||
if !ok {
|
||||
return nil, ErrSuffix
|
||||
if _, ok := amount.SetString(value); !ok {
|
||||
return Quantity{}, ErrNumeric
|
||||
}
|
||||
|
||||
// So that no one but us has to think about suffixes, remove it.
|
||||
@ -217,9 +359,11 @@ func ParseQuantity(str string) (*Quantity, error) {
|
||||
}
|
||||
|
||||
// The max is just a simple cap.
|
||||
if amount.Cmp(maxAllowed) > 0 {
|
||||
amount.Set(maxAllowed)
|
||||
// TODO: this prevents accumulating quantities greater than int64, for instance quota across a cluster
|
||||
if format == BinarySI && amount.Cmp(maxAllowed.Dec) > 0 {
|
||||
amount.Set(maxAllowed.Dec)
|
||||
}
|
||||
|
||||
if format == BinarySI && amount.Cmp(decOne) < 0 && amount.Cmp(decZero) > 0 {
|
||||
// This avoids rounding and hopefully confusion, too.
|
||||
format = DecimalSI
|
||||
@ -228,25 +372,7 @@ func ParseQuantity(str string) (*Quantity, error) {
|
||||
amount.Neg(amount)
|
||||
}
|
||||
|
||||
return &Quantity{amount, format}, nil
|
||||
}
|
||||
|
||||
// removeFactors divides in a loop; the return values have the property that
|
||||
// d == result * factor ^ times
|
||||
// d may be modified in place.
|
||||
// If d == 0, then the return values will be (0, 0)
|
||||
func removeFactors(d, factor *big.Int) (result *big.Int, times int) {
|
||||
q := big.NewInt(0)
|
||||
m := big.NewInt(0)
|
||||
for d.Cmp(bigZero) != 0 {
|
||||
q.DivMod(d, factor, m)
|
||||
if m.Cmp(bigZero) != 0 {
|
||||
break
|
||||
}
|
||||
times++
|
||||
d, q = q, d
|
||||
}
|
||||
return d, times
|
||||
return Quantity{d: infDecAmount{amount}, Format: format}, nil
|
||||
}
|
||||
|
||||
// Canonicalize returns the canonical form of q and its suffix (see comment on Quantity).
|
||||
@ -256,27 +382,22 @@ func removeFactors(d, factor *big.Int) (result *big.Int, times int) {
|
||||
// -1 and +1, it will be emitted as if q.Format were DecimalSI.
|
||||
// * Otherwise, if q.Format is set to BinarySI, frational parts of q.Amount will be
|
||||
// rounded up. (1.1i becomes 2i.)
|
||||
func (q *Quantity) Canonicalize() (string, suffix) {
|
||||
if q.Amount == nil {
|
||||
return "0", ""
|
||||
}
|
||||
|
||||
// zero is zero always
|
||||
if q.Amount.Cmp(&inf.Dec{}) == 0 {
|
||||
return "0", ""
|
||||
func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) {
|
||||
if q.IsZero() {
|
||||
return zeroBytes, nil
|
||||
}
|
||||
|
||||
var rounded CanonicalValue
|
||||
format := q.Format
|
||||
switch format {
|
||||
case DecimalExponent, DecimalSI:
|
||||
case BinarySI:
|
||||
if q.Amount.Cmp(decMinus1024) > 0 && q.Amount.Cmp(dec1024) < 0 {
|
||||
if q.CmpInt64(-1024) > 0 && q.CmpInt64(1024) < 0 {
|
||||
// This avoids rounding and hopefully confusion, too.
|
||||
format = DecimalSI
|
||||
} else {
|
||||
tmp := &inf.Dec{}
|
||||
tmp.Round(q.Amount, 0, inf.RoundUp)
|
||||
if tmp.Cmp(q.Amount) != 0 {
|
||||
var exact bool
|
||||
if rounded, exact = q.AsScale(0); !exact {
|
||||
// Don't lose precision-- show as DecimalSI
|
||||
format = DecimalSI
|
||||
}
|
||||
@ -289,125 +410,223 @@ func (q *Quantity) Canonicalize() (string, suffix) {
|
||||
// one of the other formats.
|
||||
switch format {
|
||||
case DecimalExponent, DecimalSI:
|
||||
mantissa := q.Amount.UnscaledBig()
|
||||
exponent := int(-q.Amount.Scale())
|
||||
amount := big.NewInt(0).Set(mantissa)
|
||||
// move all factors of 10 into the exponent for easy reasoning
|
||||
amount, times := removeFactors(amount, bigTen)
|
||||
exponent += times
|
||||
|
||||
// make sure exponent is a multiple of 3
|
||||
for exponent%3 != 0 {
|
||||
amount.Mul(amount, bigTen)
|
||||
exponent--
|
||||
}
|
||||
|
||||
suffix, _ := quantitySuffixer.construct(10, exponent, format)
|
||||
number := amount.String()
|
||||
number, exponent := q.AsCanonicalBytes(out)
|
||||
suffix, _ := quantitySuffixer.constructBytes(10, exponent, format)
|
||||
return number, suffix
|
||||
case BinarySI:
|
||||
tmp := &inf.Dec{}
|
||||
tmp.Round(q.Amount, 0, inf.RoundUp)
|
||||
|
||||
amount, exponent := removeFactors(tmp.UnscaledBig(), big1024)
|
||||
suffix, _ := quantitySuffixer.construct(2, exponent*10, format)
|
||||
number := amount.String()
|
||||
default:
|
||||
// format must be BinarySI
|
||||
number, exponent := rounded.AsCanonicalBase1024Bytes(out)
|
||||
suffix, _ := quantitySuffixer.constructBytes(2, exponent*10, format)
|
||||
return number, suffix
|
||||
}
|
||||
return "0", ""
|
||||
}
|
||||
|
||||
// AsInt64 returns a representation of the current value as an int64 if a fast conversion
|
||||
// is possible. If false is returned, callers must use the inf.Dec form of this quantity.
|
||||
func (q *Quantity) AsInt64() (int64, bool) {
|
||||
if q.d.Dec != nil {
|
||||
return 0, false
|
||||
}
|
||||
return q.i.AsInt64()
|
||||
}
|
||||
|
||||
// ToDec promotes the quantity in place to use an inf.Dec representation and returns itself.
|
||||
func (q *Quantity) ToDec() *Quantity {
|
||||
if q.d.Dec == nil {
|
||||
q.d.Dec = q.i.AsDec()
|
||||
q.i = int64Amount{}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
// AsDec returns the quantity as represented by a scaled inf.Dec.
|
||||
func (q *Quantity) AsDec() *inf.Dec {
|
||||
if q.d.Dec != nil {
|
||||
return q.d.Dec
|
||||
}
|
||||
q.d.Dec = q.i.AsDec()
|
||||
q.i = int64Amount{}
|
||||
return q.d.Dec
|
||||
}
|
||||
|
||||
// AsCanonicalBytes returns the canonical byte representation of this quantity as a mantissa
|
||||
// and base 10 exponent. The out byte slice may be passed to the method to avoid an extra
|
||||
// allocation.
|
||||
func (q *Quantity) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
|
||||
if q.d.Dec != nil {
|
||||
return q.d.AsCanonicalBytes(out)
|
||||
}
|
||||
return q.i.AsCanonicalBytes(out)
|
||||
}
|
||||
|
||||
// IsZero returns true if the quantity is equal to zero.
|
||||
func (q *Quantity) IsZero() bool {
|
||||
if q.d.Dec != nil {
|
||||
return q.d.Dec.Sign() == 0
|
||||
}
|
||||
return q.i.value == 0
|
||||
}
|
||||
|
||||
// Sign returns 0 if the quantity is zero, -1 if the quantity is less than zero, or 1 if the
|
||||
// quantity is greater than zero.
|
||||
func (q *Quantity) Sign() int {
|
||||
if q.d.Dec != nil {
|
||||
return q.d.Dec.Sign()
|
||||
}
|
||||
return q.i.Sign()
|
||||
}
|
||||
|
||||
// AsScaled returns the current value, rounded up to the provided scale, and returns
|
||||
// false if the scale resulted in a loss of precision.
|
||||
func (q *Quantity) AsScale(scale Scale) (CanonicalValue, bool) {
|
||||
if q.d.Dec != nil {
|
||||
return q.d.AsScale(scale)
|
||||
}
|
||||
return q.i.AsScale(scale)
|
||||
}
|
||||
|
||||
// RoundUp updates the quantity to the provided scale, ensuring that the value is at
|
||||
// least 1. False is returned if the rounding operation resulted in a loss of precision.
|
||||
// Negative numbers are rounded away from zero (-9 scale 1 rounds to -10).
|
||||
func (q *Quantity) RoundUp(scale Scale) bool {
|
||||
if q.d.Dec != nil {
|
||||
d, exact := q.d.AsScale(scale)
|
||||
q.d = d
|
||||
return exact
|
||||
}
|
||||
i, exact := q.i.AsScale(scale)
|
||||
q.i = i
|
||||
return exact
|
||||
}
|
||||
|
||||
// Add adds the provide y quantity to the current value. If the current value is zero,
|
||||
// the format of the quantity will be updated to the format of y.
|
||||
func (q *Quantity) Add(y Quantity) {
|
||||
q.s = nil
|
||||
if q.d.Dec == nil && y.d.Dec == nil {
|
||||
if q.i.value == 0 {
|
||||
q.Format = y.Format
|
||||
}
|
||||
if q.i.Add(y.i) {
|
||||
return
|
||||
}
|
||||
} else if q.IsZero() {
|
||||
q.Format = y.Format
|
||||
}
|
||||
q.ToDec().d.Dec.Add(q.d.Dec, y.AsDec())
|
||||
}
|
||||
|
||||
// Sub subtracts the provided quantity from the current value in place. If the current
|
||||
// value is zero, the format of the quantity will be updated to the format of y.
|
||||
func (q *Quantity) Sub(y Quantity) {
|
||||
q.s = nil
|
||||
if q.IsZero() {
|
||||
q.Format = y.Format
|
||||
}
|
||||
if q.d.Dec == nil && y.d.Dec == nil && q.i.Sub(y.i) {
|
||||
return
|
||||
}
|
||||
q.ToDec().d.Dec.Sub(q.d.Dec, y.AsDec())
|
||||
}
|
||||
|
||||
// Cmp returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
|
||||
// quantity is greater than y.
|
||||
func (q *Quantity) Cmp(y Quantity) int {
|
||||
if q.d.Dec == nil && y.d.Dec == nil {
|
||||
return q.i.Cmp(y.i)
|
||||
}
|
||||
return q.AsDec().Cmp(y.AsDec())
|
||||
}
|
||||
|
||||
// CmpInt64 returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
|
||||
// quantity is greater than y.
|
||||
func (q *Quantity) CmpInt64(y int64) int {
|
||||
if q.d.Dec != nil {
|
||||
return q.d.Dec.Cmp(inf.NewDec(y, inf.Scale(0)))
|
||||
}
|
||||
return q.i.Cmp(int64Amount{value: y})
|
||||
}
|
||||
|
||||
// Neg sets quantity to be the negative value of itself.
|
||||
func (q *Quantity) Neg() {
|
||||
q.s = nil
|
||||
if q.d.Dec == nil {
|
||||
q.i.value = -q.i.value
|
||||
return
|
||||
}
|
||||
q.d.Dec.Neg(q.d.Dec)
|
||||
}
|
||||
|
||||
// toBytes ensures q.s is set to a byte slice representing the canonical string form of this
|
||||
// quantity and then returns the value. CanonicalizeBytes is an expensive operation, and caching
|
||||
// this result significantly reduces the cost of normal parse / marshal operations on Quantity.
|
||||
func (q *Quantity) toBytes() []byte {
|
||||
if q.s == nil {
|
||||
result := make([]byte, 0, int64QuantityExpectedBytes)
|
||||
number, suffix := q.CanonicalizeBytes(result)
|
||||
number = append(number, suffix...)
|
||||
q.s = number
|
||||
}
|
||||
return q.s
|
||||
}
|
||||
|
||||
// int64QuantityExpectedBytes is the expected width in bytes of the canonical string representation
|
||||
// of most Quantity values.
|
||||
const int64QuantityExpectedBytes = 18
|
||||
|
||||
// String formats the Quantity as a string.
|
||||
func (q *Quantity) String() string {
|
||||
number, suffix := q.Canonicalize()
|
||||
return number + string(suffix)
|
||||
}
|
||||
|
||||
// Cmp compares q and y and returns:
|
||||
//
|
||||
// -1 if q < y
|
||||
// 0 if q == y
|
||||
// +1 if q > y
|
||||
//
|
||||
func (q *Quantity) Cmp(y Quantity) int {
|
||||
if q.Amount == nil {
|
||||
if y.Amount == nil {
|
||||
return 0
|
||||
}
|
||||
return -y.Amount.Sign()
|
||||
}
|
||||
if y.Amount == nil {
|
||||
return q.Amount.Sign()
|
||||
}
|
||||
return q.Amount.Cmp(y.Amount)
|
||||
}
|
||||
|
||||
func (q *Quantity) Add(y Quantity) error {
|
||||
switch {
|
||||
case y.Amount == nil:
|
||||
// Adding 0: do nothing.
|
||||
case q.Amount == nil:
|
||||
q.Amount = &inf.Dec{}
|
||||
return q.Add(y)
|
||||
default:
|
||||
// we want to preserve the format of the non-zero value
|
||||
zero := &inf.Dec{}
|
||||
if q.Amount.Cmp(zero) == 0 && y.Amount.Cmp(zero) != 0 {
|
||||
q.Format = y.Format
|
||||
}
|
||||
q.Amount.Add(q.Amount, y.Amount)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *Quantity) Sub(y Quantity) error {
|
||||
switch {
|
||||
case y.Amount == nil:
|
||||
// Subtracting 0: do nothing.
|
||||
case q.Amount == nil:
|
||||
q.Amount = &inf.Dec{}
|
||||
return q.Sub(y)
|
||||
default:
|
||||
// we want to preserve the format of the non-zero value
|
||||
zero := &inf.Dec{}
|
||||
if q.Amount.Cmp(zero) == 0 && y.Amount.Cmp(zero) != 0 {
|
||||
q.Format = y.Format
|
||||
}
|
||||
q.Amount.Sub(q.Amount, y.Amount)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Neg sets q to the negative value of y.
|
||||
// It updates the format of q to match y.
|
||||
func (q *Quantity) Neg(y Quantity) error {
|
||||
switch {
|
||||
case y.Amount == nil:
|
||||
*q = y
|
||||
case q.Amount == nil:
|
||||
q.Amount = &inf.Dec{}
|
||||
fallthrough
|
||||
default:
|
||||
q.Amount.Neg(y.Amount)
|
||||
q.Format = y.Format
|
||||
}
|
||||
return nil
|
||||
return string(q.toBytes())
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaller interface.
|
||||
func (q Quantity) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"` + q.String() + `"`), nil
|
||||
if q.s != nil {
|
||||
out := make([]byte, len(q.s)+2)
|
||||
out[0], out[len(out)-1] = '"', '"'
|
||||
copy(out[1:], q.s)
|
||||
return out, nil
|
||||
}
|
||||
result := make([]byte, int64QuantityExpectedBytes, int64QuantityExpectedBytes)
|
||||
result[0] = '"'
|
||||
number, suffix := q.CanonicalizeBytes(result[1:1])
|
||||
// if the same slice was returned to us that we passed in, avoid another allocation by copying number into
|
||||
// the source slice and returning that
|
||||
if len(number) > 0 && &number[0] == &result[1] && (len(number)+len(suffix)+2) <= int64QuantityExpectedBytes {
|
||||
number = append(number, suffix...)
|
||||
number = append(number, '"')
|
||||
return result[:1+len(number)], nil
|
||||
}
|
||||
// if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use
|
||||
// append
|
||||
result = result[:1]
|
||||
result = append(result, number...)
|
||||
result = append(result, suffix...)
|
||||
result = append(result, '"')
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||
func (q *Quantity) UnmarshalJSON(value []byte) error {
|
||||
str := string(value)
|
||||
parsed, err := ParseQuantity(strings.Trim(str, `"`))
|
||||
l := len(value)
|
||||
if l == 4 && bytes.Equal(value, []byte("null")) {
|
||||
q.d.Dec = nil
|
||||
q.i = int64Amount{}
|
||||
return nil
|
||||
}
|
||||
if l < 2 {
|
||||
return ErrFormatWrong
|
||||
}
|
||||
if value[0] == '"' && value[l-1] == '"' {
|
||||
value = value[1 : l-1]
|
||||
}
|
||||
parsed, err := ParseQuantity(string(value))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parsed.s = value
|
||||
// This copy is safe because parsed will not be referred to again.
|
||||
*q = *parsed
|
||||
*q = parsed
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -415,7 +634,7 @@ func (q *Quantity) UnmarshalJSON(value []byte) error {
|
||||
// value in the given format.
|
||||
func NewQuantity(value int64, format Format) *Quantity {
|
||||
return &Quantity{
|
||||
Amount: inf.NewDec(value, 0),
|
||||
i: int64Amount{value: value},
|
||||
Format: format,
|
||||
}
|
||||
}
|
||||
@ -426,7 +645,7 @@ func NewQuantity(value int64, format Format) *Quantity {
|
||||
// values x where (-1 < x < 1) && (x != 0).
|
||||
func NewMilliQuantity(value int64, format Format) *Quantity {
|
||||
return &Quantity{
|
||||
Amount: inf.NewDec(value, 3),
|
||||
i: int64Amount{value: value, scale: -3},
|
||||
Format: format,
|
||||
}
|
||||
}
|
||||
@ -435,7 +654,7 @@ func NewMilliQuantity(value int64, format Format) *Quantity {
|
||||
// value * 10^scale in DecimalSI format.
|
||||
func NewScaledQuantity(value int64, scale Scale) *Quantity {
|
||||
return &Quantity{
|
||||
Amount: inf.NewDec(value, scale.infScale()),
|
||||
i: int64Amount{value: value, scale: scale},
|
||||
Format: DecimalSI,
|
||||
}
|
||||
}
|
||||
@ -454,10 +673,12 @@ func (q *Quantity) MilliValue() int64 {
|
||||
// ScaledValue returns the value of ceil(q * 10^scale); this could overflow an int64.
|
||||
// To detect overflow, call Value() first and verify the expected magnitude.
|
||||
func (q *Quantity) ScaledValue(scale Scale) int64 {
|
||||
if q.Amount == nil {
|
||||
return 0
|
||||
if q.d.Dec == nil {
|
||||
i, _ := q.i.AsScaledInt64(scale)
|
||||
return i
|
||||
}
|
||||
return scaledValue(q.Amount.UnscaledBig(), int(q.Amount.Scale()), int(scale.infScale()))
|
||||
dec := q.d.Dec
|
||||
return scaledValue(dec.UnscaledBig(), int(dec.Scale()), int(scale.infScale()))
|
||||
}
|
||||
|
||||
// Set sets q's value to be value.
|
||||
@ -472,22 +693,25 @@ func (q *Quantity) SetMilli(value int64) {
|
||||
|
||||
// SetScaled sets q's value to be value * 10^scale
|
||||
func (q *Quantity) SetScaled(value int64, scale Scale) {
|
||||
if q.Amount == nil {
|
||||
q.Amount = &inf.Dec{}
|
||||
}
|
||||
q.Amount.SetUnscaled(value)
|
||||
q.Amount.SetScale(scale.infScale())
|
||||
q.s = nil
|
||||
q.d.Dec = nil
|
||||
q.i = int64Amount{value: value, scale: scale}
|
||||
}
|
||||
|
||||
// Copy is a convenience function that makes a deep copy for you. Non-deep
|
||||
// copies of quantities share pointers and you will regret that.
|
||||
func (q *Quantity) Copy() *Quantity {
|
||||
if q.Amount == nil {
|
||||
return NewQuantity(0, q.Format)
|
||||
if q.d.Dec == nil {
|
||||
return &Quantity{
|
||||
s: q.s,
|
||||
i: q.i,
|
||||
Format: q.Format,
|
||||
}
|
||||
}
|
||||
tmp := &inf.Dec{}
|
||||
return &Quantity{
|
||||
Amount: tmp.Set(q.Amount),
|
||||
s: q.s,
|
||||
d: infDecAmount{tmp.Set(q.d.Dec)},
|
||||
Format: q.Format,
|
||||
}
|
||||
}
|
||||
@ -504,7 +728,7 @@ func (qf qFlag) Set(val string) error {
|
||||
return err
|
||||
}
|
||||
// This copy is OK because q will not be referenced again.
|
||||
*qf.dest = *q
|
||||
*qf.dest = q
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -531,8 +755,3 @@ func QuantityFlag(flagName, defaultValue, description string) *Quantity {
|
||||
func NewQuantityFlagValue(q *Quantity) flag.Value {
|
||||
return qFlag{q}
|
||||
}
|
||||
|
||||
// infScale adapts a Scale value to an inf.Scale value.
|
||||
func (s Scale) infScale() inf.Scale {
|
||||
return inf.Scale(-s) // inf.Scale is upside-down
|
||||
}
|
||||
|
@ -17,62 +17,268 @@ limitations under the License.
|
||||
package resource
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
inf "gopkg.in/inf.v0"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
// QuantityProto is a struct that is equivalent to Quantity, but intended for
|
||||
// protobuf marshalling/unmarshalling. It is generated into a serialization
|
||||
// that matches Quantity. Do not use in Go structs.
|
||||
//
|
||||
// +protobuf=true
|
||||
type QuantityProto struct {
|
||||
// The format of the quantity
|
||||
Format Format `protobuf:"bytes,1,opt,name=format,casttype=Format"`
|
||||
// The scale dimension of the value
|
||||
Scale int32 `protobuf:"varint,2,opt,name=scale"`
|
||||
// Bigint is serialized as a raw bytes array
|
||||
Bigint []byte `protobuf:"bytes,3,opt,name=bigint"`
|
||||
var _ proto.Sizer = &Quantity{}
|
||||
|
||||
func (m *Quantity) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
// ProtoTime returns the Time as a new ProtoTime value.
|
||||
func (q *Quantity) QuantityProto() *QuantityProto {
|
||||
if q == nil {
|
||||
return &QuantityProto{}
|
||||
}
|
||||
p := &QuantityProto{
|
||||
Format: q.Format,
|
||||
}
|
||||
if q.Amount != nil {
|
||||
p.Scale = int32(q.Amount.Scale())
|
||||
p.Bigint = q.Amount.UnscaledBig().Bytes()
|
||||
}
|
||||
return p
|
||||
// MarshalTo is a customized version of the generated Protobuf unmarshaler for a struct
|
||||
// with a single string field.
|
||||
func (m *Quantity) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
|
||||
data[i] = 0xa
|
||||
i++
|
||||
// BEGIN CUSTOM MARSHAL
|
||||
out := m.toBytes()
|
||||
i = encodeVarintGenerated(data, i, uint64(len(out)))
|
||||
i += copy(data[i:], out)
|
||||
// END CUSTOM MARSHAL
|
||||
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// Size implements the protobuf marshalling interface.
|
||||
func (q *Quantity) Size() (n int) { return q.QuantityProto().Size() }
|
||||
func encodeVarintGenerated(data []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
data[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
data[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// Reset implements the protobuf marshalling interface.
|
||||
func (q *Quantity) Unmarshal(data []byte) error {
|
||||
p := QuantityProto{}
|
||||
if err := p.Unmarshal(data); err != nil {
|
||||
func (m *Quantity) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
|
||||
// BEGIN CUSTOM SIZE
|
||||
l = len(m.toBytes())
|
||||
// END CUSTOM SIZE
|
||||
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Unmarshal is a customized version of the generated Protobuf unmarshaler for a struct
|
||||
// with a single string field.
|
||||
func (m *Quantity) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Quantity: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Quantity: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field String_", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(data[iNdEx:postIndex])
|
||||
|
||||
// BEGIN CUSTOM DECODE
|
||||
p, err := ParseQuantity(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q.Format = p.Format
|
||||
b := big.NewInt(0)
|
||||
b.SetBytes(p.Bigint)
|
||||
q.Amount = inf.NewDecBig(b, inf.Scale(p.Scale))
|
||||
*m = p
|
||||
// END CUSTOM DECODE
|
||||
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal implements the protobuf marshalling interface.
|
||||
func (q *Quantity) Marshal() (data []byte, err error) {
|
||||
return q.QuantityProto().Marshal()
|
||||
func skipGenerated(data []byte) (n int, err error) {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if data[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(data[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// MarshalTo implements the protobuf marshalling interface.
|
||||
func (q *Quantity) MarshalTo(data []byte) (int, error) {
|
||||
return q.QuantityProto().MarshalTo(data)
|
||||
}
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,8 +24,9 @@ type suffix string
|
||||
|
||||
// suffixer can interpret and construct suffixes.
|
||||
type suffixer interface {
|
||||
interpret(suffix) (base, exponent int, fmt Format, ok bool)
|
||||
construct(base, exponent int, fmt Format) (s suffix, ok bool)
|
||||
interpret(suffix) (base, exponent int32, fmt Format, ok bool)
|
||||
construct(base, exponent int32, fmt Format) (s suffix, ok bool)
|
||||
constructBytes(base, exponent int32, fmt Format) (s []byte, ok bool)
|
||||
}
|
||||
|
||||
// quantitySuffixer handles suffixes for all three formats that quantity
|
||||
@ -33,12 +34,13 @@ type suffixer interface {
|
||||
var quantitySuffixer = newSuffixer()
|
||||
|
||||
type bePair struct {
|
||||
base, exponent int
|
||||
base, exponent int32
|
||||
}
|
||||
|
||||
type listSuffixer struct {
|
||||
suffixToBE map[suffix]bePair
|
||||
beToSuffix map[bePair]suffix
|
||||
beToSuffixBytes map[bePair][]byte
|
||||
}
|
||||
|
||||
func (ls *listSuffixer) addSuffix(s suffix, pair bePair) {
|
||||
@ -48,11 +50,15 @@ func (ls *listSuffixer) addSuffix(s suffix, pair bePair) {
|
||||
if ls.beToSuffix == nil {
|
||||
ls.beToSuffix = map[bePair]suffix{}
|
||||
}
|
||||
if ls.beToSuffixBytes == nil {
|
||||
ls.beToSuffixBytes = map[bePair][]byte{}
|
||||
}
|
||||
ls.suffixToBE[s] = pair
|
||||
ls.beToSuffix[pair] = s
|
||||
ls.beToSuffixBytes[pair] = []byte(s)
|
||||
}
|
||||
|
||||
func (ls *listSuffixer) lookup(s suffix) (base, exponent int, ok bool) {
|
||||
func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) {
|
||||
pair, ok := ls.suffixToBE[s]
|
||||
if !ok {
|
||||
return 0, 0, false
|
||||
@ -60,19 +66,50 @@ func (ls *listSuffixer) lookup(s suffix) (base, exponent int, ok bool) {
|
||||
return pair.base, pair.exponent, true
|
||||
}
|
||||
|
||||
func (ls *listSuffixer) construct(base, exponent int) (s suffix, ok bool) {
|
||||
func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) {
|
||||
s, ok = ls.beToSuffix[bePair{base, exponent}]
|
||||
return
|
||||
}
|
||||
|
||||
func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) {
|
||||
s, ok = ls.beToSuffixBytes[bePair{base, exponent}]
|
||||
return
|
||||
}
|
||||
|
||||
type suffixHandler struct {
|
||||
decSuffixes listSuffixer
|
||||
binSuffixes listSuffixer
|
||||
}
|
||||
|
||||
type fastLookup struct {
|
||||
*suffixHandler
|
||||
}
|
||||
|
||||
func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) {
|
||||
switch s {
|
||||
case "":
|
||||
return 10, 0, DecimalSI, true
|
||||
case "n":
|
||||
return 10, -9, DecimalSI, true
|
||||
case "u":
|
||||
return 10, -6, DecimalSI, true
|
||||
case "m":
|
||||
return 10, -3, DecimalSI, true
|
||||
case "k":
|
||||
return 10, 3, DecimalSI, true
|
||||
case "M":
|
||||
return 10, 6, DecimalSI, true
|
||||
case "G":
|
||||
return 10, 9, DecimalSI, true
|
||||
}
|
||||
return l.suffixHandler.interpret(s)
|
||||
}
|
||||
|
||||
func newSuffixer() suffixer {
|
||||
sh := &suffixHandler{}
|
||||
|
||||
// IMPORTANT: if you change this section you must change fastLookup
|
||||
|
||||
sh.binSuffixes.addSuffix("Ki", bePair{2, 10})
|
||||
sh.binSuffixes.addSuffix("Mi", bePair{2, 20})
|
||||
sh.binSuffixes.addSuffix("Gi", bePair{2, 30})
|
||||
@ -94,10 +131,10 @@ func newSuffixer() suffixer {
|
||||
sh.decSuffixes.addSuffix("P", bePair{10, 15})
|
||||
sh.decSuffixes.addSuffix("E", bePair{10, 18})
|
||||
|
||||
return sh
|
||||
return fastLookup{sh}
|
||||
}
|
||||
|
||||
func (sh *suffixHandler) construct(base, exponent int, fmt Format) (s suffix, ok bool) {
|
||||
func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) {
|
||||
switch fmt {
|
||||
case DecimalSI:
|
||||
return sh.decSuffixes.construct(base, exponent)
|
||||
@ -115,7 +152,32 @@ func (sh *suffixHandler) construct(base, exponent int, fmt Format) (s suffix, ok
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int, fmt Format, ok bool) {
|
||||
func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) {
|
||||
switch format {
|
||||
case DecimalSI:
|
||||
return sh.decSuffixes.constructBytes(base, exponent)
|
||||
case BinarySI:
|
||||
return sh.binSuffixes.constructBytes(base, exponent)
|
||||
case DecimalExponent:
|
||||
if base != 10 {
|
||||
return nil, false
|
||||
}
|
||||
if exponent == 0 {
|
||||
return nil, true
|
||||
}
|
||||
result := make([]byte, 8, 8)
|
||||
result[0] = 'e'
|
||||
number := strconv.AppendInt(result[1:1], int64(exponent), 10)
|
||||
if &result[1] == &number[0] {
|
||||
return result[:1+len(number)], true
|
||||
}
|
||||
result = append(result[:1], number...)
|
||||
return result, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt Format, ok bool) {
|
||||
// Try lookup tables first
|
||||
if b, e, ok := sh.decSuffixes.lookup(suffix); ok {
|
||||
return b, e, DecimalSI, true
|
||||
@ -129,7 +191,7 @@ func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int, fmt Forma
|
||||
if err != nil {
|
||||
return 0, 0, DecimalExponent, false
|
||||
}
|
||||
return 10, int(parsed), DecimalExponent, true
|
||||
return 10, int32(parsed), DecimalExponent, true
|
||||
}
|
||||
|
||||
return 0, 0, DecimalExponent, false
|
||||
|
@ -151,15 +151,17 @@ func PodRequestsAndLimits(pod *Pod) (reqs map[ResourceName]resource.Quantity, li
|
||||
for name, quantity := range container.Resources.Requests {
|
||||
if value, ok := reqs[name]; !ok {
|
||||
reqs[name] = *quantity.Copy()
|
||||
} else if err = value.Add(quantity); err != nil {
|
||||
return nil, nil, err
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
reqs[name] = value
|
||||
}
|
||||
}
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if value, ok := limits[name]; !ok {
|
||||
limits[name] = *quantity.Copy()
|
||||
} else if err = value.Add(quantity); err != nil {
|
||||
return nil, nil, err
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
limits[name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ func TestResourceHelpers(t *testing.T) {
|
||||
"kube.io/storage": memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); *res != cpuLimit {
|
||||
if res := resourceSpec.Limits.Cpu(); res.Cmp(cpuLimit) != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", cpuLimit, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); *res != memoryLimit {
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
resourceSpec = ResourceRequirements{
|
||||
@ -47,7 +47,7 @@ func TestResourceHelpers(t *testing.T) {
|
||||
if res := resourceSpec.Limits.Cpu(); res.Value() != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", 0, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); *res != memoryLimit {
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
}
|
||||
|
@ -25,14 +25,13 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg4_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg3_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg2_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg7_fields "k8s.io/kubernetes/pkg/fields"
|
||||
pkg6_labels "k8s.io/kubernetes/pkg/labels"
|
||||
pkg8_runtime "k8s.io/kubernetes/pkg/runtime"
|
||||
pkg6_fields "k8s.io/kubernetes/pkg/fields"
|
||||
pkg5_labels "k8s.io/kubernetes/pkg/labels"
|
||||
pkg7_runtime "k8s.io/kubernetes/pkg/runtime"
|
||||
pkg1_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg4_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -68,16 +67,15 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg4_inf_v0.Dec
|
||||
var v1 pkg3_resource.Quantity
|
||||
var v2 pkg2_unversioned.Time
|
||||
var v3 pkg7_fields.Selector
|
||||
var v4 pkg6_labels.Selector
|
||||
var v5 pkg8_runtime.Object
|
||||
var v6 pkg1_types.UID
|
||||
var v7 pkg5_intstr.IntOrString
|
||||
var v8 time.Time
|
||||
_, _, _, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6, v7, v8
|
||||
var v0 pkg3_resource.Quantity
|
||||
var v1 pkg2_unversioned.Time
|
||||
var v2 pkg6_fields.Selector
|
||||
var v3 pkg5_labels.Selector
|
||||
var v4 pkg7_runtime.Object
|
||||
var v5 pkg1_types.UID
|
||||
var v6 pkg4_intstr.IntOrString
|
||||
var v7 time.Time
|
||||
_, _, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6, v7
|
||||
}
|
||||
}
|
||||
|
||||
@ -16227,7 +16225,7 @@ func (x *HTTPGetAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
case "port":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv5 := &x.Port
|
||||
yym6 := z.DecBinary()
|
||||
@ -16306,7 +16304,7 @@ func (x *HTTPGetAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv13 := &x.Port
|
||||
yym14 := z.DecBinary()
|
||||
@ -16542,7 +16540,7 @@ func (x *TCPSocketAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
switch yys3 {
|
||||
case "port":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv4 := &x.Port
|
||||
yym5 := z.DecBinary()
|
||||
@ -16581,7 +16579,7 @@ func (x *TCPSocketAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv7 := &x.Port
|
||||
yym8 := z.DecBinary()
|
||||
@ -31535,7 +31533,7 @@ func (x *ServicePort) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
case "targetPort":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.TargetPort = pkg5_intstr.IntOrString{}
|
||||
x.TargetPort = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv7 := &x.TargetPort
|
||||
yym8 := z.DecBinary()
|
||||
@ -31628,7 +31626,7 @@ func (x *ServicePort) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.TargetPort = pkg5_intstr.IntOrString{}
|
||||
x.TargetPort = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv14 := &x.TargetPort
|
||||
yym15 := z.DecBinary()
|
||||
@ -45477,7 +45475,7 @@ func (x *List) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
_ = yym9
|
||||
if false {
|
||||
} else {
|
||||
h.encSliceruntime_Object(([]pkg8_runtime.Object)(x.Items), e)
|
||||
h.encSliceruntime_Object(([]pkg7_runtime.Object)(x.Items), e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -45491,7 +45489,7 @@ func (x *List) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
_ = yym10
|
||||
if false {
|
||||
} else {
|
||||
h.encSliceruntime_Object(([]pkg8_runtime.Object)(x.Items), e)
|
||||
h.encSliceruntime_Object(([]pkg7_runtime.Object)(x.Items), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45628,7 +45626,7 @@ func (x *List) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
_ = yym7
|
||||
if false {
|
||||
} else {
|
||||
h.decSliceruntime_Object((*[]pkg8_runtime.Object)(yyv6), d)
|
||||
h.decSliceruntime_Object((*[]pkg7_runtime.Object)(yyv6), d)
|
||||
}
|
||||
}
|
||||
case "kind":
|
||||
@ -45699,7 +45697,7 @@ func (x *List) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
_ = yym14
|
||||
if false {
|
||||
} else {
|
||||
h.decSliceruntime_Object((*[]pkg8_runtime.Object)(yyv13), d)
|
||||
h.decSliceruntime_Object((*[]pkg7_runtime.Object)(yyv13), d)
|
||||
}
|
||||
}
|
||||
yyj10++
|
||||
@ -56094,7 +56092,7 @@ func (x codecSelfer1234) decResourceList(v *ResourceList, d *codec1978.Decoder)
|
||||
yyl1 := r.ReadMapStart()
|
||||
yybh1 := z.DecBasicHandle()
|
||||
if yyv1 == nil {
|
||||
yyrl1, _ := z.DecInferLen(yyl1, yybh1.MaxInitLen, 40)
|
||||
yyrl1, _ := z.DecInferLen(yyl1, yybh1.MaxInitLen, 80)
|
||||
yyv1 = make(map[ResourceName]pkg3_resource.Quantity, yyrl1)
|
||||
*v = yyv1
|
||||
}
|
||||
@ -56643,7 +56641,7 @@ func (x codecSelfer1234) decSliceEvent(v *[]Event, d *codec1978.Decoder) {
|
||||
}
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) encSliceruntime_Object(v []pkg8_runtime.Object, e *codec1978.Encoder) {
|
||||
func (x codecSelfer1234) encSliceruntime_Object(v []pkg7_runtime.Object, e *codec1978.Encoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
@ -56665,7 +56663,7 @@ func (x codecSelfer1234) encSliceruntime_Object(v []pkg8_runtime.Object, e *code
|
||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) decSliceruntime_Object(v *[]pkg8_runtime.Object, d *codec1978.Decoder) {
|
||||
func (x codecSelfer1234) decSliceruntime_Object(v *[]pkg7_runtime.Object, d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
@ -56676,7 +56674,7 @@ func (x codecSelfer1234) decSliceruntime_Object(v *[]pkg8_runtime.Object, d *cod
|
||||
_ = yyc1
|
||||
if yyl1 == 0 {
|
||||
if yyv1 == nil {
|
||||
yyv1 = []pkg8_runtime.Object{}
|
||||
yyv1 = []pkg7_runtime.Object{}
|
||||
yyc1 = true
|
||||
} else if len(yyv1) != 0 {
|
||||
yyv1 = yyv1[:0]
|
||||
@ -56696,10 +56694,10 @@ func (x codecSelfer1234) decSliceruntime_Object(v *[]pkg8_runtime.Object, d *cod
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
} else {
|
||||
yyv1 = make([]pkg8_runtime.Object, yyrl1)
|
||||
yyv1 = make([]pkg7_runtime.Object, yyrl1)
|
||||
}
|
||||
} else {
|
||||
yyv1 = make([]pkg8_runtime.Object, yyrl1)
|
||||
yyv1 = make([]pkg7_runtime.Object, yyrl1)
|
||||
}
|
||||
yyc1 = true
|
||||
yyrr1 = len(yyv1)
|
||||
@ -56752,7 +56750,7 @@ func (x codecSelfer1234) decSliceruntime_Object(v *[]pkg8_runtime.Object, d *cod
|
||||
for ; !r.CheckBreak(); yyj1++ {
|
||||
|
||||
if yyj1 >= len(yyv1) {
|
||||
yyv1 = append(yyv1, nil) // var yyz1 pkg8_runtime.Object
|
||||
yyv1 = append(yyv1, nil) // var yyz1 pkg7_runtime.Object
|
||||
yyc1 = true
|
||||
}
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
@ -56779,7 +56777,7 @@ func (x codecSelfer1234) decSliceruntime_Object(v *[]pkg8_runtime.Object, d *cod
|
||||
yyv1 = yyv1[:yyj1]
|
||||
yyc1 = true
|
||||
} else if yyj1 == 0 && yyv1 == nil {
|
||||
yyv1 = []pkg8_runtime.Object{}
|
||||
yyv1 = []pkg7_runtime.Object{}
|
||||
yyc1 = true
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
inf "gopkg.in/inf.v0"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@ -670,8 +668,8 @@ func Convert_v1_ResourceList_To_api_ResourceList(in *ResourceList, out *api.Reso
|
||||
|
||||
// TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
|
||||
// In the future, we should instead reject values that need rounding.
|
||||
const milliScale = 3
|
||||
value.Amount.Round(value.Amount, milliScale, inf.RoundUp)
|
||||
const milliScale = -3
|
||||
value.RoundUp(milliScale)
|
||||
|
||||
converted[api.ResourceName(key)] = *value
|
||||
}
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg4_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg3_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg2_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg6_runtime "k8s.io/kubernetes/pkg/runtime"
|
||||
pkg5_runtime "k8s.io/kubernetes/pkg/runtime"
|
||||
pkg1_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg4_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg4_inf_v0.Dec
|
||||
var v1 pkg3_resource.Quantity
|
||||
var v2 pkg2_unversioned.Time
|
||||
var v3 pkg6_runtime.RawExtension
|
||||
var v4 pkg1_types.UID
|
||||
var v5 pkg5_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg3_resource.Quantity
|
||||
var v1 pkg2_unversioned.Time
|
||||
var v2 pkg5_runtime.RawExtension
|
||||
var v3 pkg1_types.UID
|
||||
var v4 pkg4_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
@ -15844,7 +15842,7 @@ func (x *HTTPGetAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
case "port":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv5 := &x.Port
|
||||
yym6 := z.DecBinary()
|
||||
@ -15923,7 +15921,7 @@ func (x *HTTPGetAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv13 := &x.Port
|
||||
yym14 := z.DecBinary()
|
||||
@ -16152,7 +16150,7 @@ func (x *TCPSocketAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
switch yys3 {
|
||||
case "port":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv4 := &x.Port
|
||||
yym5 := z.DecBinary()
|
||||
@ -16191,7 +16189,7 @@ func (x *TCPSocketAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Port = pkg5_intstr.IntOrString{}
|
||||
x.Port = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv7 := &x.Port
|
||||
yym8 := z.DecBinary()
|
||||
@ -31024,7 +31022,7 @@ func (x *ServicePort) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
case "targetPort":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.TargetPort = pkg5_intstr.IntOrString{}
|
||||
x.TargetPort = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv7 := &x.TargetPort
|
||||
yym8 := z.DecBinary()
|
||||
@ -31117,7 +31115,7 @@ func (x *ServicePort) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.TargetPort = pkg5_intstr.IntOrString{}
|
||||
x.TargetPort = pkg4_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv14 := &x.TargetPort
|
||||
yym15 := z.DecBinary()
|
||||
@ -45289,7 +45287,7 @@ func (x *List) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
_ = yym9
|
||||
if false {
|
||||
} else {
|
||||
h.encSliceruntime_RawExtension(([]pkg6_runtime.RawExtension)(x.Items), e)
|
||||
h.encSliceruntime_RawExtension(([]pkg5_runtime.RawExtension)(x.Items), e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -45303,7 +45301,7 @@ func (x *List) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
_ = yym10
|
||||
if false {
|
||||
} else {
|
||||
h.encSliceruntime_RawExtension(([]pkg6_runtime.RawExtension)(x.Items), e)
|
||||
h.encSliceruntime_RawExtension(([]pkg5_runtime.RawExtension)(x.Items), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45440,7 +45438,7 @@ func (x *List) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
_ = yym7
|
||||
if false {
|
||||
} else {
|
||||
h.decSliceruntime_RawExtension((*[]pkg6_runtime.RawExtension)(yyv6), d)
|
||||
h.decSliceruntime_RawExtension((*[]pkg5_runtime.RawExtension)(yyv6), d)
|
||||
}
|
||||
}
|
||||
case "kind":
|
||||
@ -45511,7 +45509,7 @@ func (x *List) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
_ = yym14
|
||||
if false {
|
||||
} else {
|
||||
h.decSliceruntime_RawExtension((*[]pkg6_runtime.RawExtension)(yyv13), d)
|
||||
h.decSliceruntime_RawExtension((*[]pkg5_runtime.RawExtension)(yyv13), d)
|
||||
}
|
||||
}
|
||||
yyj10++
|
||||
@ -56147,7 +56145,7 @@ func (x codecSelfer1234) decResourceList(v *ResourceList, d *codec1978.Decoder)
|
||||
yyl1 := r.ReadMapStart()
|
||||
yybh1 := z.DecBasicHandle()
|
||||
if yyv1 == nil {
|
||||
yyrl1, _ := z.DecInferLen(yyl1, yybh1.MaxInitLen, 40)
|
||||
yyrl1, _ := z.DecInferLen(yyl1, yybh1.MaxInitLen, 80)
|
||||
yyv1 = make(map[ResourceName]pkg3_resource.Quantity, yyrl1)
|
||||
*v = yyv1
|
||||
}
|
||||
@ -56696,7 +56694,7 @@ func (x codecSelfer1234) decSliceEvent(v *[]Event, d *codec1978.Decoder) {
|
||||
}
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) encSliceruntime_RawExtension(v []pkg6_runtime.RawExtension, e *codec1978.Encoder) {
|
||||
func (x codecSelfer1234) encSliceruntime_RawExtension(v []pkg5_runtime.RawExtension, e *codec1978.Encoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
@ -56717,7 +56715,7 @@ func (x codecSelfer1234) encSliceruntime_RawExtension(v []pkg6_runtime.RawExtens
|
||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExtension, d *codec1978.Decoder) {
|
||||
func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg5_runtime.RawExtension, d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
@ -56728,7 +56726,7 @@ func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExten
|
||||
_ = yyc1
|
||||
if yyl1 == 0 {
|
||||
if yyv1 == nil {
|
||||
yyv1 = []pkg6_runtime.RawExtension{}
|
||||
yyv1 = []pkg5_runtime.RawExtension{}
|
||||
yyc1 = true
|
||||
} else if len(yyv1) != 0 {
|
||||
yyv1 = yyv1[:0]
|
||||
@ -56748,10 +56746,10 @@ func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExten
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
} else {
|
||||
yyv1 = make([]pkg6_runtime.RawExtension, yyrl1)
|
||||
yyv1 = make([]pkg5_runtime.RawExtension, yyrl1)
|
||||
}
|
||||
} else {
|
||||
yyv1 = make([]pkg6_runtime.RawExtension, yyrl1)
|
||||
yyv1 = make([]pkg5_runtime.RawExtension, yyrl1)
|
||||
}
|
||||
yyc1 = true
|
||||
yyrr1 = len(yyv1)
|
||||
@ -56766,7 +56764,7 @@ func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExten
|
||||
for ; yyj1 < yyrr1; yyj1++ {
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
if r.TryDecodeAsNil() {
|
||||
yyv1[yyj1] = pkg6_runtime.RawExtension{}
|
||||
yyv1[yyj1] = pkg5_runtime.RawExtension{}
|
||||
} else {
|
||||
yyv2 := &yyv1[yyj1]
|
||||
yym3 := z.DecBinary()
|
||||
@ -56783,10 +56781,10 @@ func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExten
|
||||
}
|
||||
if yyrt1 {
|
||||
for ; yyj1 < yyl1; yyj1++ {
|
||||
yyv1 = append(yyv1, pkg6_runtime.RawExtension{})
|
||||
yyv1 = append(yyv1, pkg5_runtime.RawExtension{})
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
if r.TryDecodeAsNil() {
|
||||
yyv1[yyj1] = pkg6_runtime.RawExtension{}
|
||||
yyv1[yyj1] = pkg5_runtime.RawExtension{}
|
||||
} else {
|
||||
yyv4 := &yyv1[yyj1]
|
||||
yym5 := z.DecBinary()
|
||||
@ -56808,13 +56806,13 @@ func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExten
|
||||
for ; !r.CheckBreak(); yyj1++ {
|
||||
|
||||
if yyj1 >= len(yyv1) {
|
||||
yyv1 = append(yyv1, pkg6_runtime.RawExtension{}) // var yyz1 pkg6_runtime.RawExtension
|
||||
yyv1 = append(yyv1, pkg5_runtime.RawExtension{}) // var yyz1 pkg5_runtime.RawExtension
|
||||
yyc1 = true
|
||||
}
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
if yyj1 < len(yyv1) {
|
||||
if r.TryDecodeAsNil() {
|
||||
yyv1[yyj1] = pkg6_runtime.RawExtension{}
|
||||
yyv1[yyj1] = pkg5_runtime.RawExtension{}
|
||||
} else {
|
||||
yyv6 := &yyv1[yyj1]
|
||||
yym7 := z.DecBinary()
|
||||
@ -56837,7 +56835,7 @@ func (x codecSelfer1234) decSliceruntime_RawExtension(v *[]pkg6_runtime.RawExten
|
||||
yyv1 = yyv1[:yyj1]
|
||||
yyc1 = true
|
||||
} else if yyj1 == 0 && yyv1 == nil {
|
||||
yyv1 = []pkg6_runtime.RawExtension{}
|
||||
yyv1 = []pkg5_runtime.RawExtension{}
|
||||
yyc1 = true
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg2_api "k8s.io/kubernetes/pkg/api"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg2_api.ObjectMeta
|
||||
var v2 pkg4_resource.Quantity
|
||||
var v3 pkg1_unversioned.TypeMeta
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg2_api.ObjectMeta
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.TypeMeta
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg2_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.TypeMeta
|
||||
var v3 pkg2_v1.ObjectMeta
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg4_resource.Quantity
|
||||
var v1 pkg1_unversioned.TypeMeta
|
||||
var v2 pkg2_v1.ObjectMeta
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg2_api "k8s.io/kubernetes/pkg/api"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg2_api.ObjectMeta
|
||||
var v2 pkg4_resource.Quantity
|
||||
var v3 pkg1_unversioned.TypeMeta
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg2_api.ObjectMeta
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.TypeMeta
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg2_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.TypeMeta
|
||||
var v3 pkg2_v1.ObjectMeta
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg4_resource.Quantity
|
||||
var v1 pkg1_unversioned.TypeMeta
|
||||
var v2 pkg2_v1.ObjectMeta
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg2_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.TypeMeta
|
||||
var v3 pkg2_v1.ObjectMeta
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg4_resource.Quantity
|
||||
var v1 pkg1_unversioned.TypeMeta
|
||||
var v2 pkg2_v1.ObjectMeta
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg2_api "k8s.io/kubernetes/pkg/api"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg2_api.ObjectMeta
|
||||
var v2 pkg4_resource.Quantity
|
||||
var v3 pkg1_unversioned.LabelSelector
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg2_api.ObjectMeta
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.LabelSelector
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
@ -4916,7 +4914,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromMap(l int, d *codec1978.Dec
|
||||
switch yys3 {
|
||||
case "maxUnavailable":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.MaxUnavailable = pkg6_intstr.IntOrString{}
|
||||
x.MaxUnavailable = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv4 := &x.MaxUnavailable
|
||||
yym5 := z.DecBinary()
|
||||
@ -4931,7 +4929,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromMap(l int, d *codec1978.Dec
|
||||
}
|
||||
case "maxSurge":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.MaxSurge = pkg6_intstr.IntOrString{}
|
||||
x.MaxSurge = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv6 := &x.MaxSurge
|
||||
yym7 := z.DecBinary()
|
||||
@ -4970,7 +4968,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromArray(l int, d *codec1978.D
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.MaxUnavailable = pkg6_intstr.IntOrString{}
|
||||
x.MaxUnavailable = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv9 := &x.MaxUnavailable
|
||||
yym10 := z.DecBinary()
|
||||
@ -4995,7 +4993,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromArray(l int, d *codec1978.D
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.MaxSurge = pkg6_intstr.IntOrString{}
|
||||
x.MaxSurge = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv11 := &x.MaxSurge
|
||||
yym12 := z.DecBinary()
|
||||
@ -9593,7 +9591,7 @@ func (x *IngressBackend) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
case "servicePort":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ServicePort = pkg6_intstr.IntOrString{}
|
||||
x.ServicePort = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv5 := &x.ServicePort
|
||||
yym6 := z.DecBinary()
|
||||
@ -9648,7 +9646,7 @@ func (x *IngressBackend) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ServicePort = pkg6_intstr.IntOrString{}
|
||||
x.ServicePort = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv9 := &x.ServicePort
|
||||
yym10 := z.DecBinary()
|
||||
@ -13849,7 +13847,7 @@ func (x codecSelfer1234) decSliceCustomMetricTarget(v *[]CustomMetricTarget, d *
|
||||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 80)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
@ -13968,7 +13966,7 @@ func (x codecSelfer1234) decSliceCustomMetricCurrentStatus(v *[]CustomMetricCurr
|
||||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 80)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
@ -25,12 +25,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg5_inf_v0 "gopkg.in/inf.v0"
|
||||
pkg4_resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
pkg2_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
pkg3_types "k8s.io/kubernetes/pkg/types"
|
||||
pkg6_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
pkg5_intstr "k8s.io/kubernetes/pkg/util/intstr"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
@ -66,14 +65,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg5_inf_v0.Dec
|
||||
var v1 pkg4_resource.Quantity
|
||||
var v2 pkg1_unversioned.TypeMeta
|
||||
var v3 pkg2_v1.ObjectMeta
|
||||
var v4 pkg3_types.UID
|
||||
var v5 pkg6_intstr.IntOrString
|
||||
var v6 time.Time
|
||||
_, _, _, _, _, _, _ = v0, v1, v2, v3, v4, v5, v6
|
||||
var v0 pkg4_resource.Quantity
|
||||
var v1 pkg1_unversioned.TypeMeta
|
||||
var v2 pkg2_v1.ObjectMeta
|
||||
var v3 pkg3_types.UID
|
||||
var v4 pkg5_intstr.IntOrString
|
||||
var v5 time.Time
|
||||
_, _, _, _, _, _ = v0, v1, v2, v3, v4, v5
|
||||
}
|
||||
}
|
||||
|
||||
@ -6923,7 +6921,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromMap(l int, d *codec1978.Dec
|
||||
}
|
||||
} else {
|
||||
if x.MaxUnavailable == nil {
|
||||
x.MaxUnavailable = new(pkg6_intstr.IntOrString)
|
||||
x.MaxUnavailable = new(pkg5_intstr.IntOrString)
|
||||
}
|
||||
yym5 := z.DecBinary()
|
||||
_ = yym5
|
||||
@ -6942,7 +6940,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromMap(l int, d *codec1978.Dec
|
||||
}
|
||||
} else {
|
||||
if x.MaxSurge == nil {
|
||||
x.MaxSurge = new(pkg6_intstr.IntOrString)
|
||||
x.MaxSurge = new(pkg5_intstr.IntOrString)
|
||||
}
|
||||
yym7 := z.DecBinary()
|
||||
_ = yym7
|
||||
@ -6985,7 +6983,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromArray(l int, d *codec1978.D
|
||||
}
|
||||
} else {
|
||||
if x.MaxUnavailable == nil {
|
||||
x.MaxUnavailable = new(pkg6_intstr.IntOrString)
|
||||
x.MaxUnavailable = new(pkg5_intstr.IntOrString)
|
||||
}
|
||||
yym10 := z.DecBinary()
|
||||
_ = yym10
|
||||
@ -7014,7 +7012,7 @@ func (x *RollingUpdateDeployment) codecDecodeSelfFromArray(l int, d *codec1978.D
|
||||
}
|
||||
} else {
|
||||
if x.MaxSurge == nil {
|
||||
x.MaxSurge = new(pkg6_intstr.IntOrString)
|
||||
x.MaxSurge = new(pkg5_intstr.IntOrString)
|
||||
}
|
||||
yym12 := z.DecBinary()
|
||||
_ = yym12
|
||||
@ -13794,7 +13792,7 @@ func (x *IngressBackend) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
case "servicePort":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ServicePort = pkg6_intstr.IntOrString{}
|
||||
x.ServicePort = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv5 := &x.ServicePort
|
||||
yym6 := z.DecBinary()
|
||||
@ -13849,7 +13847,7 @@ func (x *IngressBackend) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ServicePort = pkg6_intstr.IntOrString{}
|
||||
x.ServicePort = pkg5_intstr.IntOrString{}
|
||||
} else {
|
||||
yyv9 := &x.ServicePort
|
||||
yym10 := z.DecBinary()
|
||||
@ -19393,7 +19391,7 @@ func (x codecSelfer1234) decSliceCustomMetricTarget(v *[]CustomMetricTarget, d *
|
||||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 80)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
@ -19512,7 +19510,7 @@ func (x codecSelfer1234) decSliceCustomMetricCurrentStatus(v *[]CustomMetricCurr
|
||||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 80)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
@ -44,10 +44,7 @@ func newPVC(name string) api.PersistentVolumeClaim {
|
||||
Spec: api.PersistentVolumeClaimSpec{
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.ResourceStorage: resource.Quantity{
|
||||
Amount: dec(1, 0),
|
||||
Format: resource.BinarySI,
|
||||
},
|
||||
api.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -237,7 +237,7 @@ func (a *HorizontalController) computeReplicasForCustomMetrics(hpa *autoscaling.
|
||||
}
|
||||
statusList.Items = append(statusList.Items, extensions.CustomMetricCurrentStatus{
|
||||
Name: customMetricTarget.Name,
|
||||
CurrentValue: *quantity,
|
||||
CurrentValue: quantity,
|
||||
})
|
||||
}
|
||||
byteStatusList, err := json.Marshal(statusList)
|
||||
|
@ -129,8 +129,7 @@ func (h *HeapsterMetricsClient) GetCpuConsumptionAndRequestInMillis(namespace st
|
||||
|
||||
podNames = append(podNames, pod.Name)
|
||||
for _, container := range pod.Spec.Containers {
|
||||
containerRequest := container.Resources.Requests[api.ResourceCPU]
|
||||
if containerRequest.Amount != nil {
|
||||
if containerRequest, ok := container.Resources.Requests[api.ResourceCPU]; ok {
|
||||
requestSum += containerRequest.MilliValue()
|
||||
} else {
|
||||
missing = true
|
||||
|
@ -1841,15 +1841,17 @@ func getPodsTotalRequestsAndLimits(podList *api.PodList) (reqs map[api.ResourceN
|
||||
for podReqName, podReqValue := range podReqs {
|
||||
if value, ok := reqs[podReqName]; !ok {
|
||||
reqs[podReqName] = *podReqValue.Copy()
|
||||
} else if err = value.Add(podReqValue); err != nil {
|
||||
return nil, nil, err
|
||||
} else {
|
||||
value.Add(podReqValue)
|
||||
reqs[podReqName] = value
|
||||
}
|
||||
}
|
||||
for podLimitName, podLimitValue := range podLimits {
|
||||
if value, ok := limits[podLimitName]; !ok {
|
||||
limits[podLimitName] = *podLimitValue.Copy()
|
||||
} else if err = value.Add(podLimitValue); err != nil {
|
||||
return nil, nil, err
|
||||
} else {
|
||||
value.Add(podLimitValue)
|
||||
limits[podLimitName] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ func TestGetPodsTotalRequests(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(reqs, testCase.expectedReqs) {
|
||||
if !api.Semantic.DeepEqual(reqs, testCase.expectedReqs) {
|
||||
t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs)
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ func populateResourceList(spec string) (api.ResourceList, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[resourceName] = *resourceQuantity
|
||||
result[resourceName] = resourceQuantity
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@ -458,7 +458,7 @@ func populateV1ResourceList(spec string) (v1.ResourceList, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[resourceName] = *resourceQuantity
|
||||
result[resourceName] = resourceQuantity
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
@ -378,10 +378,12 @@ func TestGenerate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
generator := BasicReplicationController{}
|
||||
for _, test := range tests {
|
||||
for i, test := range tests {
|
||||
obj, err := generator.Generate(test.params)
|
||||
t.Logf("%d: %#v", i, obj)
|
||||
if !test.expectErr && err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if test.expectErr && err != nil {
|
||||
continue
|
||||
|
@ -581,7 +581,7 @@ func (dm *DockerManager) runContainer(
|
||||
// If request is not specified, but limit is, we want request to default to limit.
|
||||
// API server does this for new containers, but we repeat this logic in Kubelet
|
||||
// for containers running on existing Kubernetes clusters.
|
||||
if cpuRequest.Amount == nil && cpuLimit.Amount != nil {
|
||||
if cpuRequest.IsZero() && !cpuLimit.IsZero() {
|
||||
cpuShares = milliCPUToShares(cpuLimit.MilliValue())
|
||||
} else {
|
||||
// if cpuRequest.Amount is nil, then milliCPUToShares will return the minimal number
|
||||
|
@ -148,7 +148,7 @@ func parseThresholdStatement(statement string) (Threshold, error) {
|
||||
return Threshold{
|
||||
Signal: signal,
|
||||
Operator: operator,
|
||||
Value: *quantity,
|
||||
Value: &quantity,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -213,14 +213,10 @@ func podUsage(podStats statsapi.PodStats) (api.ResourceList, error) {
|
||||
// disk usage (if known)
|
||||
// TODO: need to handle volumes
|
||||
for _, fsStats := range []*statsapi.FsStats{container.Rootfs, container.Logs} {
|
||||
if err := disk.Add(*diskUsage(fsStats)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disk.Add(*diskUsage(fsStats))
|
||||
}
|
||||
// memory usage (if known)
|
||||
if err := memory.Add(*memoryUsage(container.Memory)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
memory.Add(*memoryUsage(container.Memory))
|
||||
}
|
||||
return api.ResourceList{
|
||||
api.ResourceMemory: memory,
|
||||
@ -430,7 +426,7 @@ func makeSignalObservations(summaryProvider stats.SummaryProvider) (signalObserv
|
||||
statsFunc := cachedStatsFunc(summary.Pods)
|
||||
// build an evaluation context for current eviction signals
|
||||
result := signalObservations{}
|
||||
result[SignalMemoryAvailable] = *resource.NewQuantity(int64(*summary.Node.Memory.AvailableBytes), resource.BinarySI)
|
||||
result[SignalMemoryAvailable] = resource.NewQuantity(int64(*summary.Node.Memory.AvailableBytes), resource.BinarySI)
|
||||
return result, statsFunc, nil
|
||||
}
|
||||
|
||||
@ -446,7 +442,7 @@ func thresholdsMet(thresholds []Threshold, observations signalObservations) []Th
|
||||
}
|
||||
// determine if we have met the specified threshold
|
||||
thresholdMet := false
|
||||
thresholdResult := threshold.Value.Cmp(observed)
|
||||
thresholdResult := threshold.Value.Cmp(*observed)
|
||||
switch threshold.Operator {
|
||||
case OpLessThan:
|
||||
thresholdMet = thresholdResult > 0
|
||||
@ -538,7 +534,7 @@ func hasNodeCondition(inputs []api.NodeConditionType, item api.NodeConditionType
|
||||
// hasThreshold returns true if the node condition is in the input list
|
||||
func hasThreshold(inputs []Threshold, item Threshold) bool {
|
||||
for _, input := range inputs {
|
||||
if input.GracePeriod == item.GracePeriod && input.Operator == item.Operator && input.Signal == item.Signal && input.Value.Cmp(item.Value) == 0 {
|
||||
if input.GracePeriod == item.GracePeriod && input.Operator == item.Operator && input.Signal == item.Signal && input.Value.Cmp(*item.Value) == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,11 @@ import (
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
)
|
||||
|
||||
func quantityMustParse(value string) *resource.Quantity {
|
||||
q := resource.MustParse(value)
|
||||
return &q
|
||||
}
|
||||
|
||||
func TestParseThresholdConfig(t *testing.T) {
|
||||
gracePeriod, _ := time.ParseDuration("30s")
|
||||
testCases := map[string]struct {
|
||||
@ -55,12 +60,12 @@ func TestParseThresholdConfig(t *testing.T) {
|
||||
{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("150Mi"),
|
||||
Value: quantityMustParse("150Mi"),
|
||||
},
|
||||
{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("300Mi"),
|
||||
Value: quantityMustParse("300Mi"),
|
||||
GracePeriod: gracePeriod,
|
||||
},
|
||||
},
|
||||
@ -145,7 +150,7 @@ func thresholdEqual(a Threshold, b Threshold) bool {
|
||||
return a.GracePeriod == b.GracePeriod &&
|
||||
a.Operator == b.Operator &&
|
||||
a.Signal == b.Signal &&
|
||||
a.Value.Cmp(b.Value) == 0
|
||||
a.Value.Cmp(*b.Value) == 0
|
||||
}
|
||||
|
||||
// TestOrderedByQoS ensures we order BestEffort < Burstable < Guaranteed
|
||||
@ -348,7 +353,7 @@ func TestThresholdsMet(t *testing.T) {
|
||||
hardThreshold := Threshold{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("1Gi"),
|
||||
Value: quantityMustParse("1Gi"),
|
||||
}
|
||||
testCases := map[string]struct {
|
||||
thresholds []Threshold
|
||||
@ -363,14 +368,14 @@ func TestThresholdsMet(t *testing.T) {
|
||||
"threshold-met": {
|
||||
thresholds: []Threshold{hardThreshold},
|
||||
observations: signalObservations{
|
||||
SignalMemoryAvailable: resource.MustParse("500Mi"),
|
||||
SignalMemoryAvailable: quantityMustParse("500Mi"),
|
||||
},
|
||||
result: []Threshold{hardThreshold},
|
||||
},
|
||||
"threshold-not-met": {
|
||||
thresholds: []Threshold{hardThreshold},
|
||||
observations: signalObservations{
|
||||
SignalMemoryAvailable: resource.MustParse("2Gi"),
|
||||
SignalMemoryAvailable: quantityMustParse("2Gi"),
|
||||
},
|
||||
result: []Threshold{},
|
||||
},
|
||||
@ -387,7 +392,7 @@ func TestThresholdsFirstObservedAt(t *testing.T) {
|
||||
hardThreshold := Threshold{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("1Gi"),
|
||||
Value: quantityMustParse("1Gi"),
|
||||
}
|
||||
now := unversioned.Now()
|
||||
oldTime := unversioned.NewTime(now.Time.Add(-1 * time.Minute))
|
||||
@ -435,12 +440,12 @@ func TestThresholdsMetGracePeriod(t *testing.T) {
|
||||
hardThreshold := Threshold{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("1Gi"),
|
||||
Value: quantityMustParse("1Gi"),
|
||||
}
|
||||
softThreshold := Threshold{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("2Gi"),
|
||||
Value: quantityMustParse("2Gi"),
|
||||
GracePeriod: 1 * time.Minute,
|
||||
}
|
||||
oldTime := unversioned.NewTime(now.Time.Add(-2 * time.Minute))
|
||||
|
@ -103,7 +103,7 @@ func TestMemoryPressure(t *testing.T) {
|
||||
{
|
||||
Signal: SignalMemoryAvailable,
|
||||
Operator: OpLessThan,
|
||||
Value: resource.MustParse("1Gi"),
|
||||
Value: quantityMustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ type Threshold struct {
|
||||
// Operator represents a relationship of a signal to a value.
|
||||
Operator ThresholdOperator
|
||||
// value is a quantity associated with the signal that is evaluated against the specified operator.
|
||||
Value resource.Quantity
|
||||
Value *resource.Quantity
|
||||
// GracePeriod represents the amount of time that a threshold must be met before eviction is triggered.
|
||||
GracePeriod time.Duration
|
||||
}
|
||||
@ -88,7 +88,7 @@ type statsFunc func(pod *api.Pod) (statsapi.PodStats, bool)
|
||||
type rankFunc func(pods []*api.Pod, stats statsFunc)
|
||||
|
||||
// signalObservations maps a signal to an observed quantity
|
||||
type signalObservations map[Signal]resource.Quantity
|
||||
type signalObservations map[Signal]*resource.Quantity
|
||||
|
||||
// thresholdsObservedAt maps a threshold to a time that it was observed
|
||||
type thresholdsObservedAt map[Threshold]time.Time
|
||||
|
@ -3051,7 +3051,7 @@ func (kl *Kubelet) setNodeStatusMachineInfo(node *api.Node) {
|
||||
if kl.reservation.Kubernetes != nil {
|
||||
value.Sub(kl.reservation.Kubernetes[k])
|
||||
}
|
||||
if value.Amount != nil && value.Amount.Sign() < 0 {
|
||||
if value.Sign() < 0 {
|
||||
// Negative Allocatable resources don't make sense.
|
||||
value.Set(0)
|
||||
}
|
||||
|
@ -3853,16 +3853,16 @@ func TestExtractBandwidthResources(t *testing.T) {
|
||||
},
|
||||
{
|
||||
pod: testPod("10M", ""),
|
||||
expectedIngress: ten,
|
||||
expectedIngress: &ten,
|
||||
},
|
||||
{
|
||||
pod: testPod("", "10M"),
|
||||
expectedEgress: ten,
|
||||
expectedEgress: &ten,
|
||||
},
|
||||
{
|
||||
pod: testPod("4M", "20M"),
|
||||
expectedIngress: four,
|
||||
expectedEgress: twenty,
|
||||
expectedIngress: &four,
|
||||
expectedEgress: &twenty,
|
||||
},
|
||||
{
|
||||
pod: testPod("foo", ""),
|
||||
|
@ -93,7 +93,7 @@ func Subtract(a api.ResourceList, b api.ResourceList) api.ResourceList {
|
||||
for key, value := range b {
|
||||
if _, found := result[key]; !found {
|
||||
quantity := *value.Copy()
|
||||
quantity.Neg(value)
|
||||
quantity.Neg()
|
||||
result[key] = quantity
|
||||
}
|
||||
}
|
||||
|
@ -38,18 +38,22 @@ func validateBandwidthIsReasonable(rsrc *resource.Quantity) error {
|
||||
func ExtractPodBandwidthResources(podAnnotations map[string]string) (ingress, egress *resource.Quantity, err error) {
|
||||
str, found := podAnnotations["kubernetes.io/ingress-bandwidth"]
|
||||
if found {
|
||||
if ingress, err = resource.ParseQuantity(str); err != nil {
|
||||
ingressValue, err := resource.ParseQuantity(str)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ingress = &ingressValue
|
||||
if err := validateBandwidthIsReasonable(ingress); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
str, found = podAnnotations["kubernetes.io/egress-bandwidth"]
|
||||
if found {
|
||||
if egress, err = resource.ParseQuantity(str); err != nil {
|
||||
egressValue, err := resource.ParseQuantity(str)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
egress = &egressValue
|
||||
if err := validateBandwidthIsReasonable(egress); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -383,5 +383,5 @@ func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
|
||||
return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
|
||||
}
|
||||
used.Format = resource.BinarySI
|
||||
return used, nil
|
||||
return &used, nil
|
||||
}
|
||||
|
@ -43,5 +43,5 @@ func Du(path string) (*resource.Quantity, error) {
|
||||
return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
|
||||
}
|
||||
used.Format = resource.BinarySI
|
||||
return used, nil
|
||||
return &used, nil
|
||||
}
|
||||
|
@ -57,5 +57,5 @@ func Du(path string) (*resource.Quantity, error) {
|
||||
return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
|
||||
}
|
||||
used.Format = resource.BinarySI
|
||||
return used, nil
|
||||
return &used, nil
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ var _ = framework.KubeDescribe("LimitRange", func() {
|
||||
})
|
||||
|
||||
func equalResourceRequirement(expected api.ResourceRequirements, actual api.ResourceRequirements) error {
|
||||
framework.Logf("Verifying requests: expected %s with actual %s", expected.Requests, actual.Requests)
|
||||
framework.Logf("Verifying requests: expected %v with actual %v", expected.Requests, actual.Requests)
|
||||
err := equalResourceList(expected.Requests, actual.Requests)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -314,10 +314,7 @@ func newPVC(name string) api.PersistentVolumeClaim {
|
||||
},
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.ResourceStorage: resource.Quantity{
|
||||
Amount: dec(1, 0),
|
||||
Format: resource.BinarySI,
|
||||
},
|
||||
api.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
8
vendor/github.com/appc/spec/schema/types/isolator_resources.go
generated
vendored
8
vendor/github.com/appc/spec/schema/types/isolator_resources.go
generated
vendored
@ -155,8 +155,8 @@ func NewResourceCPUIsolator(request, limit string) (*ResourceCPU, error) {
|
||||
res := &ResourceCPU{
|
||||
ResourceBase{
|
||||
resourceValue{
|
||||
Request: req,
|
||||
Limit: lim,
|
||||
Request: &req,
|
||||
Limit: &lim,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -209,8 +209,8 @@ func NewResourceMemoryIsolator(request, limit string) (*ResourceMemory, error) {
|
||||
res := &ResourceMemory{
|
||||
ResourceBase{
|
||||
resourceValue{
|
||||
Request: req,
|
||||
Limit: lim,
|
||||
Request: &req,
|
||||
Limit: &lim,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user