Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9775a12

Browse files
authored
Merge pull request#2216 from rkschamer/master
Adding utils.format_quantity
2 parentsa5c3373 +0f3f8ec commit9775a12

File tree

2 files changed

+187
-8
lines changed

2 files changed

+187
-8
lines changed

‎kubernetes/e2e_test/test_utils.py

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
# under the License.
1414

1515
importunittest
16+
fromdecimalimportDecimal
1617
fromosimportpath
1718

1819
importyaml
1920

20-
fromkubernetesimportutils,client
21+
fromkubernetesimportclient,utils
2122
fromkubernetes.client.restimportApiException
2223
fromkubernetes.e2e_testimportbase
24+
fromkubernetes.utilsimportquantity
2325

2426

2527
classTestUtils(unittest.TestCase):
@@ -605,3 +607,113 @@ def test_create_from_list_in_multi_resource_yaml_namespaced(self):
605607
name="mock-pod-1",namespace=self.test_namespace,body={})
606608
app_api.delete_namespaced_deployment(
607609
name="mock",namespace=self.test_namespace,body={})
610+
611+
612+
classTestUtilsUnitTests(unittest.TestCase):
613+
614+
deftest_parse_quantity(self):
615+
# == trivial returns ==
616+
self.assertEqual(quantity.parse_quantity(Decimal(1)),Decimal(1))
617+
self.assertEqual(quantity.parse_quantity(float(1)),Decimal(1))
618+
self.assertEqual(quantity.parse_quantity(1),Decimal(1))
619+
620+
# == exceptions ==
621+
self.assertRaises(
622+
ValueError,lambda:quantity.parse_quantity("1000kb")
623+
)
624+
self.assertRaises(
625+
ValueError,lambda:quantity.parse_quantity("1000ki")
626+
)
627+
self.assertRaises(ValueError,lambda:quantity.parse_quantity("1000foo"))
628+
self.assertRaises(ValueError,lambda:quantity.parse_quantity("foo"))
629+
630+
# == no suffix ==
631+
self.assertEqual(quantity.parse_quantity("1000"),Decimal(1000))
632+
633+
# == base 1024 ==
634+
self.assertEqual(quantity.parse_quantity("1Ki"),Decimal(1024))
635+
self.assertEqual(quantity.parse_quantity("1Mi"),Decimal(1024**2))
636+
self.assertEqual(quantity.parse_quantity("1Gi"),Decimal(1024**3))
637+
self.assertEqual(quantity.parse_quantity("1Ti"),Decimal(1024**4))
638+
self.assertEqual(quantity.parse_quantity("1Pi"),Decimal(1024**5))
639+
self.assertEqual(quantity.parse_quantity("1Ei"),Decimal(1024**6))
640+
self.assertEqual(quantity.parse_quantity("1024Ki"),Decimal(1024**2))
641+
self.assertEqual(quantity.parse_quantity("0.5Ki"),Decimal(512))
642+
643+
# == base 1000 ==
644+
self.assertAlmostEqual(quantity.parse_quantity("1n"),Decimal(0.000_000_001))
645+
self.assertAlmostEqual(quantity.parse_quantity("1u"),Decimal(0.000_001))
646+
self.assertAlmostEqual(quantity.parse_quantity("1m"),Decimal(0.001))
647+
self.assertEqual(quantity.parse_quantity("1k"),Decimal(1_000))
648+
self.assertEqual(quantity.parse_quantity("1M"),Decimal(1_000_000))
649+
self.assertEqual(quantity.parse_quantity("1G"),Decimal(1_000_000_000))
650+
self.assertEqual(quantity.parse_quantity("1T"),Decimal(1_000_000_000_000))
651+
self.assertEqual(quantity.parse_quantity("1P"),Decimal(1_000_000_000_000_000))
652+
self.assertEqual(
653+
quantity.parse_quantity("1E"),Decimal(1_000_000_000_000_000_000))
654+
self.assertEqual(quantity.parse_quantity("1000k"),Decimal(1_000_000))
655+
self.assertEqual(quantity.parse_quantity("500k"),Decimal(500_000))
656+
657+
deftest_format_quantity(self):
658+
"""Unit test for quantity.format_quantity. Testing the different SI suffixes and
659+
function should return the expected string"""
660+
661+
# == unknown suffixes ==
662+
self.assertRaises(
663+
ValueError,lambda:quantity.format_quantity(Decimal(1_000),"kb")
664+
)
665+
self.assertRaises(
666+
ValueError,lambda:quantity.format_quantity(Decimal(1_000),"ki")
667+
)
668+
self.assertRaises(
669+
ValueError,lambda:quantity.format_quantity(Decimal(1_000),"foo")
670+
)
671+
672+
# == no suffix ==
673+
self.assertEqual(quantity.format_quantity(Decimal(1_000),""),"1000")
674+
self.assertEqual(quantity.format_quantity(Decimal(1_000),None),"1000")
675+
676+
# == base 1024 ==
677+
self.assertEqual(quantity.format_quantity(Decimal(1024),"Ki"),"1Ki")
678+
self.assertEqual(quantity.format_quantity(Decimal(1024**2),"Mi"),"1Mi")
679+
self.assertEqual(quantity.format_quantity(Decimal(1024**3),"Gi"),"1Gi")
680+
self.assertEqual(quantity.format_quantity(Decimal(1024**4),"Ti"),"1Ti")
681+
self.assertEqual(quantity.format_quantity(Decimal(1024**5),"Pi"),"1Pi")
682+
self.assertEqual(quantity.format_quantity(Decimal(1024**6),"Ei"),"1Ei")
683+
self.assertEqual(quantity.format_quantity(Decimal(1024**2),"Ki"),"1024Ki")
684+
self.assertEqual(quantity.format_quantity(Decimal((1024**3)/2),"Gi"),"0.5Gi")
685+
# Decimal((1024**3)/3) are 0.3333333333333333148296162562Gi; expecting to
686+
# be quantized to 0.3Gi
687+
self.assertEqual(
688+
quantity.format_quantity(
689+
Decimal(
690+
(1024**3)/3),
691+
"Gi",
692+
quantize=Decimal(.5)),
693+
"0.3Gi")
694+
695+
# == base 1000 ==
696+
self.assertEqual(quantity.format_quantity(Decimal(0.000_000_001),"n"),"1n")
697+
self.assertEqual(quantity.format_quantity(Decimal(0.000_001),"u"),"1u")
698+
self.assertEqual(quantity.format_quantity(Decimal(0.001),"m"),"1m")
699+
self.assertEqual(quantity.format_quantity(Decimal(1_000),"k"),"1k")
700+
self.assertEqual(quantity.format_quantity(Decimal(1_000_000),"M"),"1M")
701+
self.assertEqual(quantity.format_quantity(Decimal(1_000_000_000),"G"),"1G")
702+
self.assertEqual(
703+
quantity.format_quantity(Decimal(1_000_000_000_000),"T"),"1T"
704+
)
705+
self.assertEqual(
706+
quantity.format_quantity(Decimal(1_000_000_000_000_000),"P"),"1P"
707+
)
708+
self.assertEqual(
709+
quantity.format_quantity(Decimal(1_000_000_000_000_000_000),"E"),"1E"
710+
)
711+
self.assertEqual(quantity.format_quantity(Decimal(1_000_000),"k"),"1000k")
712+
# Decimal(1_000_000/3) are 333.3333333333333139307796955k; expecting to
713+
# be quantized to 333k
714+
self.assertEqual(
715+
quantity.format_quantity(
716+
Decimal(1_000_000/3),"k",quantize=Decimal(1000)
717+
),
718+
"333k",
719+
)

‎kubernetes/utils/quantity.py

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@
1313
# limitations under the License.
1414
fromdecimalimportDecimal,InvalidOperation
1515

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+
1629

1730
defparse_quantity(quantity):
1831
"""
@@ -35,17 +48,14 @@ def parse_quantity(quantity):
3548
ifisinstance(quantity, (int,float,Decimal)):
3649
returnDecimal(quantity)
3750

38-
exponents= {"n":-3,"u":-2,"m":-1,"K":1,"k":1,"M":2,
39-
"G":3,"T":4,"P":5,"E":6}
40-
4151
quantity=str(quantity)
4252
number=quantity
4353
suffix=None
4454
iflen(quantity)>=2andquantity[-1]=="i":
45-
ifquantity[-2]inexponents:
55+
ifquantity[-2]in_EXPONENTS:
4656
number=quantity[:-2]
4757
suffix=quantity[-2:]
48-
eliflen(quantity)>=1andquantity[-1]inexponents:
58+
eliflen(quantity)>=1andquantity[-1]in_EXPONENTS:
4959
number=quantity[:-1]
5060
suffix=quantity[-1:]
5161

@@ -68,8 +78,65 @@ def parse_quantity(quantity):
6878
ifsuffix=="ki":
6979
raiseValueError("{} has unknown suffix".format(quantity))
7080

71-
ifsuffix[0]notinexponents:
81+
ifsuffix[0]notin_EXPONENTS:
7282
raiseValueError("{} has unknown suffix".format(quantity))
7383

74-
exponent=Decimal(exponents[suffix[0]])
84+
exponent=Decimal(_EXPONENTS[suffix[0]])
7585
returnnumber* (base**exponent)
86+
87+
88+
defformat_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+
ifnotsuffix:
124+
returnstr(quantity_value)
125+
126+
ifsuffix.endswith("i"):
127+
base=1024
128+
eliflen(suffix)==1:
129+
base=1000
130+
else:
131+
raiseValueError(f"{quantity_value} has unknown suffix")
132+
133+
ifsuffix=="ki":
134+
raiseValueError(f"{quantity_value} has unknown suffix")
135+
136+
ifsuffix[0]notin_EXPONENTS:
137+
raiseValueError(f"{quantity_value} has unknown suffix")
138+
139+
different_scale=quantity_value/Decimal(base**_EXPONENTS[suffix[0]])
140+
ifquantize:
141+
different_scale=different_scale.quantize(quantize)
142+
returnstr(different_scale)+suffix

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp