Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to process a str expression directly as a list #37

Merged
merged 1 commit into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions generic_k8s_webhook/config_parser/operator_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class MetaOperatorParser:
def __init__(self, list_op_parser_classes: list[type], raw_str_parser: expr_parser.IRawStringParser) -> None:
self.dict_op_parser = {}
self.dict_op_parser: dict[str, OperatorParser] = {}
for op_parser_class in list_op_parser_classes:
# Make sure that op_parser_class is a proper "OperatorParser" derived class
if (
Expand All @@ -25,15 +25,17 @@ def __init__(self, list_op_parser_classes: list[type], raw_str_parser: expr_pars

self.raw_str_parser = raw_str_parser

def parse(self, op_spec: dict | str, path_op: str) -> operators.Operator:
def parse(self, op_spec: dict | str | list, path_op: str) -> operators.Operator:
if isinstance(op_spec, dict):
return self._parse_dict(op_spec, path_op)
if isinstance(op_spec, str):
return self._parse_str(op_spec, path_op)
if isinstance(op_spec, list):
return self._parse_list(op_spec, path_op)
raise RuntimeError(f"Cannot parse the type {type(op_spec)}. It must be dict or str")

def _parse_dict(self, op_spec: dict, path_op: str) -> operators.Operator:
"""It's used to parse a structured operator. Example:
"""It's used to parse a structured operator with a well defined key. Example:

```yaml
sum:
Expand Down Expand Up @@ -63,6 +65,12 @@ def _parse_str(self, op_spec: str, path_op: str) -> operators.Operator:
except Exception as e:
raise ParsingException(f"Error when parsing {path_op}") from e

def _parse_list(self, op_spec: list, path_op: str) -> operators.Operator:
if "list" not in self.dict_op_parser:
raise RuntimeError(f"Couldn't find the 'list' parser to parse the list in {path_op}")
list_parser = self.dict_op_parser["list"]
return list_parser.parse(op_spec, path_op)


class OperatorParser(abc.ABC):
def __init__(self, meta_op_parser: MetaOperatorParser) -> None:
Expand All @@ -80,14 +88,7 @@ def get_name(cls) -> str:

class BinaryOpParser(OperatorParser):
def parse(self, op_inputs: dict | list, path_op: str) -> operators.BinaryOp:
if isinstance(op_inputs, list):
list_parser = ListParser(self.meta_op_parser)
args = list_parser.parse(op_inputs, path_op)
elif isinstance(op_inputs, dict):
args = self.meta_op_parser.parse(op_inputs, path_op)
else:
raise ValueError(f"Expected dict or list as input, but got {op_inputs}")

args = self.meta_op_parser.parse(op_inputs, path_op)
try:
return self.get_operator_cls()(args)
except TypeError as e:
Expand Down
7 changes: 5 additions & 2 deletions generic_k8s_webhook/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ def cli(args):
accept, patch = webhook.process_manifest(k8s_manifest)
if not accept:
sys.exit(1)
# Show the patch if it's not None
if patch:
# Show the patch if it's not None
if args.show_patch:
print(json.dumps(patch.patch, indent=2))
else:
print(yaml.dump(patch.apply(k8s_manifest), indent=2))
else:
logging.info("No changes")
sys.exit(0)
logging.error(
f"Couldn't find a webhook called {args.wh_name}. "
Expand Down Expand Up @@ -95,11 +97,12 @@ def parse_args() -> argparse.ArgumentParser:

def main():
args = parse_args()
logging.basicConfig(format="%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s")
if args.verbose > 0:
logging.basicConfig(
format="%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s", level=logging.INFO
)
else:
logging.basicConfig(format="%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s")
args.func(args)


Expand Down
28 changes: 28 additions & 0 deletions tests/conditions_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,31 @@ test_suites:
- name: istio
maxCPU: 2
expected_result: [true]
- name: BINARY_OP_ON_STR_LIST_MAP
tests:
- schemas: [v1beta1]
cases:
- condition:
all: .nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution.*.preference.matchExpressions.* -> .key != "myKey"
context:
- nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: key1
- preference:
matchExpressions:
- key: key2
expected_result: true
- condition:
all: .nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution.*.preference.matchExpressions.* -> .key != "myKey"
context:
- nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: key1
- preference:
matchExpressions:
- key: myKey
expected_result: false
Loading