From 891fc353d5884be81d929001b5fda32247da11c7 Mon Sep 17 00:00:00 2001 From: Tomas Sladecek Date: Mon, 30 Oct 2023 12:21:46 +0100 Subject: [PATCH] allow enforcing integer values in patches --- README.md | 1 + examples/base/hpa.yaml | 30 ++++++++++++++++++++++++++++++ examples/patches/hpa_patch.yaml | 11 +++++++++++ src/ksux/src/patch.py | 7 +++++++ src/ksux/src/schemas.py | 1 + src/ksux/tests/test_patch.py | 16 ++++++++++++++-- 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 examples/base/hpa.yaml create mode 100644 examples/patches/hpa_patch.yaml diff --git a/README.md b/README.md index 2aa15d7..c3deec5 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ ops: path: value: action: + enforce_integer: list_key: ``` diff --git a/examples/base/hpa.yaml b/examples/base/hpa.yaml new file mode 100644 index 0000000..e5c95eb --- /dev/null +++ b/examples/base/hpa.yaml @@ -0,0 +1,30 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: hpa +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: hpa + minReplicas: 1 + maxReplicas: 1 + metrics: + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 + behavior: + scaleDown: + policies: + - type: Percent + value: 50 + periodSeconds: 30 \ No newline at end of file diff --git a/examples/patches/hpa_patch.yaml b/examples/patches/hpa_patch.yaml new file mode 100644 index 0000000..8c3fad4 --- /dev/null +++ b/examples/patches/hpa_patch.yaml @@ -0,0 +1,11 @@ +name: horizontal pod autoscaler patch +ops: +- action: replace + name: replace max replicas value + path: /spec/maxReplicas + value: 3 + enforce_integer: true +target: + apiVersion: autoscaling/v2 + kind: HorizontalPodAutoscaler + name: hpa diff --git a/src/ksux/src/patch.py b/src/ksux/src/patch.py index 334864d..1a82059 100644 --- a/src/ksux/src/patch.py +++ b/src/ksux/src/patch.py @@ -22,6 +22,13 @@ def validate_patch(patch: dict) -> Patch: logging.error(f'Patch {patch} did not pass validation. See required fields') exit(1) else: + for op in validated.ops: + if op.enforce_integer: + try: + op.value = int(op.value) + except ValueError: + logging.error(f'Cannot convert "{op.value}" to int for patch: {validated}') + return validated diff --git a/src/ksux/src/schemas.py b/src/ksux/src/schemas.py index 0d638c1..8d9cbca 100644 --- a/src/ksux/src/schemas.py +++ b/src/ksux/src/schemas.py @@ -36,6 +36,7 @@ class Op(BaseModel): name: str path: str value: Optional[Union[str, int, dict, list]] + enforce_integer: bool = False action: Action list_key: str = 'name' diff --git a/src/ksux/tests/test_patch.py b/src/ksux/tests/test_patch.py index cf363f3..61826cc 100644 --- a/src/ksux/tests/test_patch.py +++ b/src/ksux/tests/test_patch.py @@ -4,7 +4,7 @@ import pytest from pydantic import ValidationError -from src.ksux.src.patch import read_patches, get_real_path, apply_patch +from src.ksux.src.patch import read_patches, get_real_path, apply_patch, validate_patch from src.ksux.src.schemas import Patch, Op, Action from src.ksux.tests.config import settings @@ -22,7 +22,8 @@ def get_valid_patch() -> dict: "name": "example op", "path": "/spec/replicas", "action": "replace", - "value": 2 + "value": "2", + "enforce_integer": False } ] } @@ -32,6 +33,17 @@ def test_validate_patch_valid_patch(): valid = get_valid_patch() assert Patch(**valid) + # Test enforce integer False + patch = get_valid_patch() + patch["ops"][0]["enforce_integer"] = False + validated = validate_patch(patch) + assert isinstance(validated.ops[0].value, str) + + # Test enforce integer True + patch["ops"][0]["enforce_integer"] = True + validated = validate_patch(patch) + assert isinstance(validated.ops[0].value, int) + # value can be omitted for action remove valid_patch_action_remove_missing_value = get_valid_patch() valid_patch_action_remove_missing_value['ops'][0]['action'] = 'remove'