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()