13
13
# limitations under the License.
14
14
from decimal import Decimal , InvalidOperation
15
15
16
+ _EXPONENTS = {
17
+ "n" : - 3 ,
18
+ "u" : - 2 ,
19
+ "m" : - 1 ,
20
+ "K" : 1 ,
21
+ "k" : 1 ,
22
+ "M" : 2 ,
23
+ "G" : 3 ,
24
+ "T" : 4 ,
25
+ "P" : 5 ,
26
+ "E" : 6 ,
27
+ }
28
+
16
29
17
30
def parse_quantity (quantity ):
18
31
"""
@@ -35,17 +48,14 @@ def parse_quantity(quantity):
35
48
if isinstance (quantity , (int , float , Decimal )):
36
49
return Decimal (quantity )
37
50
38
- exponents = {"n" : - 3 , "u" : - 2 , "m" : - 1 , "K" : 1 , "k" : 1 , "M" : 2 ,
39
- "G" : 3 , "T" : 4 , "P" : 5 , "E" : 6 }
40
-
41
51
quantity = str (quantity )
42
52
number = quantity
43
53
suffix = None
44
54
if len (quantity ) >= 2 and quantity [- 1 ] == "i" :
45
- if quantity [- 2 ] in exponents :
55
+ if quantity [- 2 ] in _EXPONENTS :
46
56
number = quantity [:- 2 ]
47
57
suffix = quantity [- 2 :]
48
- elif len (quantity ) >= 1 and quantity [- 1 ] in exponents :
58
+ elif len (quantity ) >= 1 and quantity [- 1 ] in _EXPONENTS :
49
59
number = quantity [:- 1 ]
50
60
suffix = quantity [- 1 :]
51
61
@@ -68,8 +78,62 @@ def parse_quantity(quantity):
68
78
if suffix == "ki" :
69
79
raise ValueError ("{} has unknown suffix" .format (quantity ))
70
80
71
- if suffix [0 ] not in exponents :
81
+ if suffix [0 ] not in _EXPONENTS :
72
82
raise ValueError ("{} has unknown suffix" .format (quantity ))
73
83
74
- exponent = Decimal (exponents [suffix [0 ]])
84
+ exponent = Decimal (_EXPONENTS [suffix [0 ]])
75
85
return number * (base ** exponent )
86
+
87
+
88
+ def format_quantity (quantity_value , suffix , quantize = None ) -> str :
89
+ """
90
+ Takes a decimal and produces a string value in kubernetes' canonical quantity form,
91
+ like "200Mi".Users can specify an additional decimal number to quantize the output.
92
+
93
+ Example - Relatively increase pod memory limits:
94
+
95
+ # retrieve my_pod
96
+ current_memory: Decimal = parse_quantity(my_pod.spec.containers[0].resources.limits.memory)
97
+ desired_memory = current_memory * 1.2
98
+ desired_memory_str = format_quantity(desired_memory, suffix="Gi", quantize=Decimal(1))
99
+ # patch pod with desired_memory_str
100
+
101
+ 'quantize=Decimal(1)' ensures that the result does not contain any fractional digits.
102
+
103
+ Supported SI suffixes:
104
+ base1024: Ki | Mi | Gi | Ti | Pi | Ei
105
+ base1000: n | u | m | "" | k | M | G | T | P | E
106
+
107
+ See https://github.com/kubernetes/apimachinery/blob/master/pkg/api/resource/quantity.go
108
+
109
+ Input:
110
+ quantity: Decimal. Quantity as a number which is supposed to converted to a string
111
+ with SI suffix.
112
+ suffix: string. The desired suffix/unit-of-measure of the output string
113
+ quantize: Decimal. Can be used to round/quantize the value before the string
114
+ is returned. Defaults to None.
115
+
116
+ Returns:
117
+ string. Canonical Kubernetes quantity string containing the SI suffix.
118
+
119
+ Raises:
120
+ ValueError if the SI suffix is not supported.
121
+ """
122
+
123
+ if suffix .endswith ("i" ):
124
+ base = 1024
125
+ elif len (suffix ) == 1 :
126
+ base = 1000
127
+ else :
128
+ raise ValueError (f"{ quantity_value } has unknown suffix" )
129
+
130
+ if suffix == "ki" :
131
+ raise ValueError (f"{ quantity_value } has unknown suffix" )
132
+
133
+ if suffix [0 ] not in _EXPONENTS :
134
+ raise ValueError (f"{ quantity_value } has unknown suffix" )
135
+
136
+ different_scale = quantity_value / Decimal (base ** _EXPONENTS [suffix [0 ]])
137
+ if quantize :
138
+ different_scale = different_scale .quantize (quantize )
139
+ return str (different_scale ) + suffix
0 commit comments