OpenStack Service Types Authority
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.3 KiB

  1. # Copyright (c) 2017 Red Hat, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. # implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import glob
  16. import json
  17. import operator
  18. import os
  19. import shutil
  20. import sys
  21. import requests
  22. HTTP_LOCATION = 'https://service-types.openstack.org/service-types.json'
  23. SPECS_BASE = 'http://specs.openstack.org/openstack'
  24. OUTDIR = 'doc/build/html'
  25. HEADER = '''<div class="section" id="service-types-authority">
  26. <h1>OpenStack Service Types Authority Data</h1>
  27. <p>For more information on the files, see:
  28. <a href='{specs_base}/service-types-authority'>
  29. {specs_base}/service-types-authority</a></p>
  30. <p>For more information on using the information, see:
  31. <a href='{specs_base}/api-wg/'>
  32. {specs_base}/api-wg/</a></p>
  33. <p>The canonical source data is kept in git at:
  34. <a href='https://opendev.org/openstack/service-types-authority'>
  35. https://opendev.org/openstack/service-types-authority</a></p>
  36. <p>The canonical YAML source can be found at:
  37. <a href='{specs_base}/service-types-authority/#service-data'>
  38. {specs_base}/service-types-authority/#service-data
  39. </a></p>
  40. </div>
  41. <h2>Latest file is <a href="./{latest_file}">{latest_file}</a></h2>
  42. '''
  43. def is_data_equal(old, new):
  44. # Check specific data - largely because services is a list where order
  45. # does not matter, and version/sha are always going to be different.
  46. # Order DOES matter in alias lists and mappings though, so just do
  47. # normal equality on the service dicts and reverse and forward mappings.
  48. if old.keys() != new.keys():
  49. return False
  50. if (sorted(old['services'], key=operator.itemgetter('service_type')) !=
  51. sorted(new['services'], key=operator.itemgetter('service_type'))):
  52. return False
  53. if old['reverse'] != new['reverse']:
  54. return False
  55. if old['forward'] != new['forward']:
  56. return False
  57. return True
  58. def should_publish_data():
  59. current_contents = json.load(open('service-types.json', 'r'))
  60. try:
  61. response = requests.get(HTTP_LOCATION)
  62. response.raise_for_status()
  63. existing_contents = response.json()
  64. except (requests.HTTPError, requests.ConnectionError) as e:
  65. print("Failed to fetch current service-types.json. Assuming data"
  66. " needs to be published. Error: {error}".format(error=str(e)))
  67. return (True, current_contents['version'])
  68. # If our contents are not the same as published, we need to publish
  69. should_publish = not is_data_equal(existing_contents, current_contents)
  70. if should_publish:
  71. return (True, current_contents['version'])
  72. else:
  73. return (False, existing_contents['version'])
  74. def main():
  75. if not os.path.exists(OUTDIR):
  76. os.makedirs(OUTDIR)
  77. elif not os.path.isdir(OUTDIR):
  78. print(
  79. "{outdir} exists but is not a directory. Aborting!".format(
  80. outdir=OUTDIR))
  81. return 1
  82. # It's fine to always copy the json schema
  83. # The schema can update - descriptions can be cleaned up, format regexes
  84. # can get fixed.
  85. # schema updates that don't work with the existing file won't land (we
  86. # gate on them).
  87. to_copy = glob.glob('*schema.json')
  88. should_publish, latest_version = should_publish_data()
  89. if should_publish:
  90. to_copy += glob.glob('service-types.json*')
  91. else:
  92. print("Data in existing file matches {version} data."
  93. " Not publishing".format(version=latest_version))
  94. for filename in to_copy:
  95. shutil.copyfile(filename, os.path.join(OUTDIR, filename))
  96. latest_file = 'service-types.json.{version}'.format(version=latest_version)
  97. with open('{outdir}/HEADER.html'.format(outdir=OUTDIR), 'w') as header:
  98. header.write(HEADER.format(latest_file=latest_file,
  99. specs_base=SPECS_BASE))
  100. return 0
  101. if __name__ == '__main__':
  102. sys.exit(main())