33
44
55class ConfigValidator :
6-
7- REQUIRED_KEYS : Dict [str , List [str ]] = {
6+ REQUIRED_KEYS : Dict [str , List [Any ]] = {
87 "config" : ["pipeline.id" , "config.string" ],
9- "expectation" : ["status" , "symptom" , "diagnosis" , "impacts" , "details" ],
10- "diagnosis" : ["cause" ],
11- "impacts" : ["description" , "impact_areas" ],
12- "details" : ["run_state" ],
8+ "expectation" : ["status" , "symptom" , {"diagnosis" : ["cause" ]},
9+ {"impacts" : ["description" , "impact_areas" ], "details" : ["run_state" ]}]
1310 }
1411
1512 def __init__ (self ):
1613 self .yaml_content = None
1714
18- def __validate_keys (self , actual_keys : List [str ], expected_keys : List [str ], section : str ) -> bool :
19- """Validate the keys at the current level."""
20- missing_keys = set (expected_keys ) - set (actual_keys )
21- if len (missing_keys ) == len (expected_keys ):
22- print (f"Missing keys in { section } : { missing_keys } " )
23- return False
24- return True
25-
26- def __validate_config (self , config_list : List [Dict [str , Any ]]) -> bool :
27- """Validate the 'config' section."""
28- for config_item in config_list :
29- if not self .__validate_keys (list (config_item .keys ()), self .REQUIRED_KEYS ["config" ], "config" ):
15+ def __validate_keys (self , data : Dict [str , Any ], required_keys : Dict [str , List [Any ]]) -> bool :
16+ for key , required_list in required_keys .items ():
17+ if key not in data :
18+ print (f"Missing top-level key: { key } " )
3019 return False
20+ for item in required_list :
21+ if isinstance (item , str ):
22+ if not self .__check_nested_key (data [key ], item ):
23+ print (f"Missing nested key: { item } in { key } " )
24+ return False
25+ elif isinstance (item , dict ):
26+ for sub_key , sub_value in item .items ():
27+ if sub_key not in data [key ]:
28+ print (f"Missing key: { sub_key } in { key } " )
29+ return False
30+ # Recursively check the nested dictionary
31+ if not self .__validate_keys (data [key ][sub_key ], {sub_key : sub_value }):
32+ return False
3133 return True
3234
33- def __validate_expectation (self , expectation_list : List [ Dict [str , Any ]] ) -> bool :
34- """Validate the 'expectation' section."""
35- for expectation_item in expectation_list :
36- if not self . __validate_keys ( list ( expectation_item . keys ()), self . REQUIRED_KEYS [ "expectation" ], "expectation" ) :
35+ def __check_nested_key (self , data : Dict [str , Any ], nested_key : str ) -> bool :
36+ keys = nested_key . split ( '.' )
37+ for key in keys :
38+ if key not in data :
3739 return False
38- if "diagnosis" in expectation_item :
39- for diagnosis in expectation_item ["diagnosis" ]:
40- if not self .__validate_keys (list (diagnosis .keys ()), self .REQUIRED_KEYS ["diagnosis" ], "diagnosis" ):
41- return False
42- if "impacts" in expectation_item :
43- for impact in expectation_item ["impacts" ]:
44- if not self .__validate_keys (list (impact .keys ()), self .REQUIRED_KEYS ["impacts" ], "impacts" ):
45- return False
46- if "details" in expectation_item :
47- for detail in expectation_item ["details" ]:
48- if not self .__validate_keys (list (detail .keys ()), self .REQUIRED_KEYS ["details" ], "details" ):
49- return False
5040 return True
5141
5242 def load (self , file_path : str ) -> None :
5343 """Load the YAML file content into self.yaml_content."""
54- self .yaml_content : Union [ List [ Dict [str , Any ]], None ] = None
44+ self .yaml_content : [ Dict [str , Any ]] = None
5545 try :
5646 with open (file_path , 'r' ) as file :
5747 self .yaml_content = yaml .safe_load (file )
@@ -65,16 +55,19 @@ def is_valid(self) -> bool:
6555 print (f"YAML content is empty." )
6656 return False
6757
68- if not isinstance (self .yaml_content , list ):
69- print (f"YAML structure is not as expected, it should start with a list ." )
58+ if not isinstance (self .yaml_content , Dict ):
59+ print (f"YAML structure is not as expected, it should start with a Dict ." )
7060 return False
7161
62+ required_config_keys = list (self .REQUIRED_KEYS .keys ())
7263 for item in self .yaml_content :
73- if "config" in item and not self .__validate_config (item ["config" ]):
74- return False
75-
76- if "expectation" in item and not self .__validate_expectation (item ["expectation" ]):
64+ if item == "name" :
65+ continue
66+ if item not in required_config_keys :
7767 return False
7868
79- print (f"YAML file validation successful!" )
69+ if self .__validate_keys (self .yaml_content , self .REQUIRED_KEYS ):
70+ print ("Valid YAML content detected." )
71+ else :
72+ print ("YAML validation failed." )
8073 return True
0 commit comments