2 Copyright 2014 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
28 "github.com/google/gofuzz"
32 // IntOrString is a type that can hold an int32 or a string. When used in
33 // JSON or YAML marshalling and unmarshalling, it produces or consumes the
34 // inner type. This allows you to have, for example, a JSON field that can
35 // accept a name or number.
36 // TODO: Rename to Int32OrString
39 // +protobuf.options.(gogoproto.goproto_stringer)=false
40 // +k8s:openapi-gen=true
41 type IntOrString struct {
42 Type Type `protobuf:"varint,1,opt,name=type,casttype=Type"`
43 IntVal int32 `protobuf:"varint,2,opt,name=intVal"`
44 StrVal string `protobuf:"bytes,3,opt,name=strVal"`
47 // Type represents the stored type of IntOrString.
51 Int Type = iota // The IntOrString holds an int.
52 String // The IntOrString holds a string.
55 // FromInt creates an IntOrString object with an int32 value. It is
56 // your responsibility not to call this method with a value greater
58 // TODO: convert to (val int32)
59 func FromInt(val int) IntOrString {
60 if val > math.MaxInt32 || val < math.MinInt32 {
61 klog.Errorf("value: %d overflows int32\n%s\n", val, debug.Stack())
63 return IntOrString{Type: Int, IntVal: int32(val)}
66 // FromString creates an IntOrString object with a string value.
67 func FromString(val string) IntOrString {
68 return IntOrString{Type: String, StrVal: val}
71 // Parse the given string and try to convert it to an integer before
72 // setting it as a string value.
73 func Parse(val string) IntOrString {
74 i, err := strconv.Atoi(val)
76 return FromString(val)
81 // UnmarshalJSON implements the json.Unmarshaller interface.
82 func (intstr *IntOrString) UnmarshalJSON(value []byte) error {
85 return json.Unmarshal(value, &intstr.StrVal)
88 return json.Unmarshal(value, &intstr.IntVal)
91 // String returns the string value, or the Itoa of the int value.
92 func (intstr *IntOrString) String() string {
93 if intstr.Type == String {
96 return strconv.Itoa(intstr.IntValue())
99 // IntValue returns the IntVal if type Int, or if
100 // it is a String, will attempt a conversion to int.
101 func (intstr *IntOrString) IntValue() int {
102 if intstr.Type == String {
103 i, _ := strconv.Atoi(intstr.StrVal)
106 return int(intstr.IntVal)
109 // MarshalJSON implements the json.Marshaller interface.
110 func (intstr IntOrString) MarshalJSON() ([]byte, error) {
113 return json.Marshal(intstr.IntVal)
115 return json.Marshal(intstr.StrVal)
117 return []byte{}, fmt.Errorf("impossible IntOrString.Type")
121 // OpenAPISchemaType is used by the kube-openapi generator when constructing
122 // the OpenAPI spec of this type.
124 // See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
125 func (_ IntOrString) OpenAPISchemaType() []string { return []string{"string"} }
127 // OpenAPISchemaFormat is used by the kube-openapi generator when constructing
128 // the OpenAPI spec of this type.
129 func (_ IntOrString) OpenAPISchemaFormat() string { return "int-or-string" }
131 func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
137 c.Fuzz(&intstr.IntVal)
142 c.Fuzz(&intstr.StrVal)
146 func ValueOrDefault(intOrPercent *IntOrString, defaultValue IntOrString) *IntOrString {
147 if intOrPercent == nil {
153 func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool) (int, error) {
154 if intOrPercent == nil {
155 return 0, errors.New("nil value for IntOrString")
157 value, isPercent, err := getIntOrPercentValue(intOrPercent)
159 return 0, fmt.Errorf("invalid value for IntOrString: %v", err)
163 value = int(math.Ceil(float64(value) * (float64(total)) / 100))
165 value = int(math.Floor(float64(value) * (float64(total)) / 100))
171 func getIntOrPercentValue(intOrStr *IntOrString) (int, bool, error) {
172 switch intOrStr.Type {
174 return intOrStr.IntValue(), false, nil
176 s := strings.Replace(intOrStr.StrVal, "%", "", -1)
177 v, err := strconv.Atoi(s)
179 return 0, false, fmt.Errorf("invalid value %q: %v", intOrStr.StrVal, err)
181 return int(v), true, nil
183 return 0, false, fmt.Errorf("invalid type: neither int nor percentage")