generate.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/env python
  2. '''
  3. Generate the openshift-ansible/roles/lib_openshift_cli/library/ modules.
  4. '''
  5. import argparse
  6. import os
  7. import yaml
  8. import six
  9. OPENSHIFT_ANSIBLE_PATH = os.path.dirname(os.path.realpath(__file__))
  10. OPENSHIFT_ANSIBLE_SOURCES_PATH = os.path.join(OPENSHIFT_ANSIBLE_PATH, 'sources.yml') # noqa: E501
  11. LIBRARY = os.path.join(OPENSHIFT_ANSIBLE_PATH, '..', 'library/')
  12. class GenerateAnsibleException(Exception):
  13. '''General Exception for generate function'''
  14. pass
  15. def parse_args():
  16. '''parse arguments to generate'''
  17. parser = argparse.ArgumentParser(description="Generate ansible modules.")
  18. parser.add_argument('--verify', action='store_true', default=False,
  19. help='Verify library code matches the generated code.')
  20. return parser.parse_args()
  21. def fragment_banner(fragment_path, side, data):
  22. """Generate a banner to wrap around file fragments
  23. :param string fragment_path: A path to a module fragment
  24. :param string side: ONE OF: "header", "footer"
  25. :param StringIO data: A StringIO object to write the banner to
  26. """
  27. side_msg = {
  28. "header": "Begin included fragment: {}",
  29. "footer": "End included fragment: {}"
  30. }
  31. annotation = side_msg[side].format(fragment_path)
  32. banner = """
  33. # -*- -*- -*- {} -*- -*- -*-
  34. """.format(annotation)
  35. # Why skip?
  36. #
  37. # * 'generated' - This is the head of the script, we don't want to
  38. # put comments before the #!shebang
  39. #
  40. # * 'license' - Wrapping this just seemed like gratuitous extra
  41. if ("generated" not in fragment_path) and ("license" not in fragment_path):
  42. data.write(banner)
  43. # Make it self-contained testable
  44. return banner
  45. def generate(parts):
  46. '''generate the source code for the ansible modules
  47. :param Array parts: An array of paths (strings) to module fragments
  48. '''
  49. data = six.StringIO()
  50. for fpart in parts:
  51. # first line is pylint disable so skip it
  52. with open(os.path.join(OPENSHIFT_ANSIBLE_PATH, fpart)) as pfd:
  53. fragment_banner(fpart, "header", data)
  54. for idx, line in enumerate(pfd):
  55. if idx in [0, 1] and 'flake8: noqa' in line or 'pylint: skip-file' in line: # noqa: E501
  56. continue
  57. data.write(line)
  58. fragment_banner(fpart, "footer", data)
  59. return data
  60. def get_sources():
  61. '''return the path to the generate sources'''
  62. return yaml.load(open(OPENSHIFT_ANSIBLE_SOURCES_PATH).read())
  63. def verify():
  64. '''verify if the generated code matches the library code'''
  65. for fname, parts in get_sources().items():
  66. data = generate(parts)
  67. fname = os.path.join(LIBRARY, fname)
  68. if not open(fname).read() == data.getvalue():
  69. raise GenerateAnsibleException('Generated content does not match for %s' % fname)
  70. def main():
  71. ''' combine the necessary files to create the ansible module '''
  72. args = parse_args()
  73. if args.verify:
  74. verify()
  75. for fname, parts in get_sources().items():
  76. data = generate(parts)
  77. fname = os.path.join(LIBRARY, fname)
  78. with open(fname, 'w') as afd:
  79. afd.seek(0)
  80. afd.write(data.getvalue())
  81. if __name__ == '__main__':
  82. main()