k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/experiment/compare-yaml.py (about) 1 #!/usr/bin/env python3 2 3 # Copyright 2020 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """Recursive YAML comparator 18 19 This script allow the user to compare two directories containing 20 YAML files in the same folder structure. 21 22 Usage: ./compare-yaml.py path1 path2 23 24 It will walk through all files in path1 and compare them with the same file 25 found in path2. Comparison is semantic and not affected by the order of lists. 26 """ 27 28 import operator 29 import os 30 import sys 31 32 import yaml 33 34 35 def loadfile(f): 36 """Loads a YAML file containing several documents into a list of objects 37 38 :param f: string containing the path to the file to load 39 :return: list of loaded objects 40 """ 41 try: 42 return list(yaml.safe_load_all(open(f))) 43 except Exception as e: 44 print('Exception caught loading', f, e) 45 raise 46 47 48 def compare(f1, left, right): 49 """Compares the same filename from two path roots and prints the difference to stdout 50 51 :param f1: full path to the first file 52 :param left: root of f1 path to construct relative path 53 :param right: second root to deduct f2 path 54 :return: None 55 """ 56 f2 = os.path.join(right, os.path.relpath(f1, left)) 57 if not os.path.isfile(f2): 58 print('Cannot find', f2) 59 return 60 d1s = loadfile(f1) 61 d2s = loadfile(f2) 62 if not all(map(operator.eq, d1s, d2s)): 63 print('meld', f1, f2) 64 65 66 def main(): 67 if len(sys.argv) != 3: 68 sys.exit('Provide path1 and path2') 69 left = sys.argv[1] 70 right = sys.argv[2] 71 for root, _, files in os.walk(left): 72 for name in files: 73 f = os.path.join(root, name) 74 if not os.path.isfile(f): 75 print('Skipping', f) 76 continue 77 if f.endswith('.yaml'): 78 compare(f, left, right) 79 80 81 if __name__ == "__main__": 82 main()