Skip to content

Commit

Permalink
Merge pull request #121 from ClarkSource/fix-standardization
Browse files Browse the repository at this point in the history
fix: regex matches on int caused errors
  • Loading branch information
AFriemann authored Jul 12, 2022
2 parents 89a0c57 + 5b8ad8a commit ec7e24a
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ quickly verify the written templates.
* `get_secret(key: str)` - provides a secret value from a given provider (see [here](#managing-secrets))
* `bool(value: Any)` - casts value to boolean ("true", "on", "yes", "1", 1 are considered as `True`)
* `sanitize_label(value: str)` - sanitizes label values according to kubernetes spec
* `sanitize_cpu(value: str | int)` - sanitize cpu value to millicores
* `sanitize_memory(value: str | int)` - sanitize memory value to megabyte (note: values in scientific notation need to be converted to strings)
* `standardize_cpu(value: str | int)` - standardize cpu value to millicores (as int)
* `standardize_memory(value: str | int)` - standardize memory value to megabyte (as int; note: values in scientific notation need to be converted to strings)

## Configuration inheritance

Expand Down
26 changes: 15 additions & 11 deletions k8t/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,31 +118,33 @@ def sanitize_label(value: str) -> str:
return re.sub(r"(^[^a-z0-9A-Z]|[^a-z0-9A-Z]$|[^a-z0-9A-Z_.-])", "X", value[:63])


def sanitize_cpu(value: str) -> str:
def sanitize_cpu(value: Any) -> str:
"""
sanitize cpu resource values to millicores.
"""
return f"{standardize_cpu(value)}m"


def sanitize_memory(value: str) -> str:
def sanitize_memory(value: Any) -> str:
"""
sanitize memory resource values to megabyte.
"""
return f"{standardize_memory(value)}M"


def standardize_cpu(value: str) -> int:
def standardize_cpu(value: Any) -> int:
"""
standardize cpu values to millicores.
"""

value_millis: int

if re.fullmatch(r"^[0-9]+(\.[0-9]+)?$", value):
str_value = str(value)

if re.fullmatch(r"^[0-9]+(\.[0-9]+)?$", str_value):
value_millis = int(float(value) * 1000)
elif re.fullmatch(r"^[0-9]+m$", value):
value_millis = int(value[:-1])
elif re.fullmatch(r"^[0-9]+m$", str_value):
value_millis = int(str_value[:-1])
else:
raise ValueError(f"invalid cpu value: {value}")

Expand All @@ -152,7 +154,7 @@ def standardize_cpu(value: str) -> int:
return value_millis


def standardize_memory(value: str) -> int:
def standardize_memory(value: Any) -> int:
"""
standardize memory values to a common notation.
Expand All @@ -161,11 +163,13 @@ def standardize_memory(value: str) -> int:

value_mb: int

if re.fullmatch(r"^[0-9]+([EPTGMk]i?)?$", value):
str_value = str(value)

if re.fullmatch(r"^[0-9]+([EPTGMk]i?)?$", str_value):
value_mb = util.memory_to_mb(f"{value}B")
elif re.fullmatch(r"^[0-9]+m$", value):
value_mb = util.memory_to_mb(f"{int(value[:-1]) / 1000}B")
elif re.fullmatch(r"^[0-9]+e[0-9]+$", value):
elif re.fullmatch(r"^[0-9]+m$", str_value):
value_mb = util.memory_to_mb(f"{int(str_value[:-1]) / 1000}B")
elif re.fullmatch(r"^[0-9]+e[0-9]+$", str_value):
value_mb = util.memory_to_mb(f"{float(value)}B")
else:
raise ValueError(f"invalid memory value: {value}")
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ known_first_party = ["k8t"]
norecursedirs = [".tox", ".direnv", ".git", ".python3"]
python_files = ["*.py"]
testpaths = ["tests"]

[tool.pyright]
include = ["k8t"]
pythonPlatform = "Linux"
14 changes: 14 additions & 0 deletions tests/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,25 @@ def test_sanitize_label():
def test_sanitize_cpu():
assert sanitize_cpu("200m") == "200m"
assert sanitize_cpu("0.5") == "500m"
assert sanitize_cpu(0.5) == "500m"
assert sanitize_cpu("1") == "1000m"
assert sanitize_cpu(1) == "1000m"
assert sanitize_cpu("92") == "92000m"
assert sanitize_cpu(92) == "92000m"
assert sanitize_cpu("1.8") == "1800m"
assert sanitize_cpu(1.8) == "1800m"
assert sanitize_cpu("3000m") == "3000m"

assert sanitize_cpu("0.1") == "100m"
assert sanitize_cpu(0.1) == "100m"
assert sanitize_cpu("0.01") == "10m"
assert sanitize_cpu(0.01) == "10m"
assert sanitize_cpu("0.001") == "1m"
assert sanitize_cpu(0.001) == "1m"

with pytest.raises(ValueError):
assert sanitize_cpu("0.0001") == "0.1m"
assert sanitize_cpu(0.0001) == "0.1m"


def test_sanitize_memory():
Expand All @@ -146,16 +154,22 @@ def compare(size: str, value: int, precision: float = 0.008) -> bool:
assert sanitize_memory("100000000m") == "0.1M"

assert sanitize_memory("1289748") == "1M"
assert sanitize_memory(1289748) == "1M"
with pytest.raises(ValueError):
assert sanitize_memory("128974") == "0M"

# precision can vary between systems, values should be approximately 129MB
assert compare(sanitize_memory("129e6"), 129)
assert compare(sanitize_memory("129M"), 129)
assert compare(sanitize_memory("128974848"), 129)
assert compare(sanitize_memory(128974848), 129)
assert compare(sanitize_memory("128974848000m"), 129)
assert compare(sanitize_memory("123Mi"), 129)

with pytest.raises(ValueError):
# TODO: this is a known limitation
assert compare(sanitize_memory(129e6), 129)

assert sanitize_memory("300000000000m") == "300M"
assert sanitize_memory("20000000000m") == "20M"
assert sanitize_memory("20005000000m") == "20M"
Expand Down

0 comments on commit ec7e24a

Please sign in to comment.