a16d0893b0
The .rst Guideline files currently say that they're generated from "the master JSON verison" but don't actually contain a link to their JSON counterparts. This patch makes that reference a hyperlink so folks can more easily locate the JSON files that are the authoritative documents. This is especially useful when viewing rendered versions of the RST docs. The patch also adjusts the script we use to generate the RST docs from their JSON sources so future Guidelines include similar linkage. While we're at it, we've also removed a chunk of code in the RST generator script so that it doesn't rely on the "name" field since we never really added those fields universally, which could cause the script to fail. Instead we just use the "project" field. Further, a few capabilities that are marked as removed are lacking the aforementioned "project" field, so those have been added where they were missing. Following the changes to the RST generating script, it has been re-run so that the existing 2015 Guideline RST documents have the same formatting. While the formatting has changed (added links and modified capitalization), the content has not (no capabilities or tests added/removed). Co-Authored-By: Mark T. Voelker <mvoelker@vmware.com> Co-Authored-By: Rob Hirschfeld <rob@zehicle.com> Change-Id: Idbdd7d6825aa8af2404b9e2791fa67240cdef239
183 lines
5.2 KiB
Python
Executable File
183 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2015 Alexander Hirschfeld
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
# This was build for python 2.7, The print statements are failing with
|
|
# Python 3.X
|
|
|
|
import json
|
|
import sys
|
|
import textwrap
|
|
|
|
|
|
def printHelpArrays(input):
|
|
if(len(input) == 0):
|
|
return 'None'
|
|
output = ""
|
|
for i in input:
|
|
output = output + i.capitalize() + ', '
|
|
|
|
return output[0:-2]
|
|
|
|
wrapper = textwrap.TextWrapper(width=79, subsequent_indent=' ')
|
|
|
|
inFileName = "NONE"
|
|
for potentialFile in sys.argv:
|
|
if ".json" in potentialFile:
|
|
inFileName = potentialFile
|
|
|
|
if inFileName is "NONE":
|
|
print "Please pass the JSON file"
|
|
sys.exit(1)
|
|
|
|
print "reading from", inFileName
|
|
|
|
|
|
with open(inFileName) as f:
|
|
data = json.load(f)
|
|
|
|
if not isinstance(data, dict):
|
|
print 'Make sure this is a valid file'
|
|
sys.exit(1)
|
|
|
|
outFileName = inFileName.replace("json", "rst")
|
|
|
|
|
|
print "writing to", outFileName
|
|
|
|
|
|
# intro
|
|
with open(outFileName, "w") as outFile:
|
|
if data.get('id') is None:
|
|
print 'Make sure there is a valid id'
|
|
sys.exit(1)
|
|
|
|
line01 = "OpenStack DefCore %s" % data["id"]
|
|
|
|
outFile.write('='*len(line01) + '\n')
|
|
outFile.write(line01 + '\n')
|
|
outFile.write('='*len(line01) + '\n')
|
|
|
|
# Nonlooping
|
|
if data.get('platform') is None:
|
|
print "The platform section is not found"
|
|
sys.exit(1)
|
|
|
|
# Correct Source
|
|
if data.get('source') != 'http://git.openstack.org/cgit/openstack/defcore/':
|
|
print "The expected DefCore source not found"
|
|
sys.exit(1)
|
|
|
|
outFile.write("""
|
|
:Status: {status}
|
|
:Replaces: {replaces}
|
|
:JSON Master: http://git.openstack.org/cgit/openstack/defcore/tree/{id}.json
|
|
|
|
This document outlines the mandatory capabilities and designated
|
|
sections required to exist in a software installation in order to
|
|
be eligible to use marks controlled by the OpenStack Foundation.
|
|
|
|
This document was generated from the `master JSON version <{id}.json>`_.
|
|
|
|
Releases Covered
|
|
==============================
|
|
Applies to {releases}
|
|
|
|
Platform Components
|
|
==============================
|
|
:Required: {platformRequired}
|
|
|
|
:Advisory: {platformAdvisory}
|
|
|
|
:Deprecated: {platformDepric}
|
|
|
|
:Removed: {platformRemoved}
|
|
""".format(status=data.get("status"),
|
|
replaces=data.get("replaces"),
|
|
id=data.get("id"),
|
|
releases=printHelpArrays(data.get("releases")),
|
|
platformRequired=printHelpArrays(data["platform"].get("required")),
|
|
platformAdvisory=printHelpArrays(data["platform"].get("advisory")),
|
|
platformDepric=printHelpArrays(data["platform"].get("deprecated")),
|
|
platformRemoved=printHelpArrays(data["platform"].get("removed"))))
|
|
|
|
# looping
|
|
if data.get('components') is None:
|
|
print "No components found"
|
|
sys.exit(1)
|
|
|
|
components = sorted(data["components"].keys())
|
|
order = ["required", "advisory", "deprecated", "removed"]
|
|
for component in components:
|
|
|
|
outFile.write("""
|
|
|
|
|
|
|
|
{component} Component Capabilities
|
|
""".format(component=component.capitalize()))
|
|
outFile.write('='*(len(component) + 23)) # footer
|
|
|
|
for event in order:
|
|
|
|
outFile.write("\n{event} Capabilities\n".format(
|
|
event=event.capitalize()))
|
|
outFile.write("-" * (len(event) + 15) + "\n")
|
|
|
|
if(len(data['components'][component][event]) == 0):
|
|
outFile.write("None\n")
|
|
|
|
for req in data['components'][component][event]:
|
|
outFile.write("* {name} ({project})\n".format(
|
|
name=req,
|
|
project=data["capabilities"][req].get("project").capitalize()))
|
|
|
|
# Designated -Sections
|
|
|
|
if 'designated-sections' not in data:
|
|
print "designated-sections not in json file"
|
|
sys.exit(1)
|
|
|
|
outFile.write("""
|
|
|
|
Designated Sections
|
|
=====================================
|
|
|
|
The following designated sections apply to the same releases as
|
|
this specification.""")
|
|
order = ['required', 'advisory', 'deprecated', 'removed']
|
|
desig = data.get("designated-sections")
|
|
for event in order:
|
|
|
|
outFile.write('\n\n{event} Designated Sections\n'.format(
|
|
event=event.capitalize()))
|
|
# +20 is for length of header
|
|
outFile.write('-'*(len(event) + 20) + '\n\n')
|
|
|
|
names = sorted(desig[event].keys())
|
|
if len(names) is 0:
|
|
outFile.write('None')
|
|
|
|
outlines = []
|
|
for name in names:
|
|
outlines.append(
|
|
wrapper.fill(
|
|
"* {name} : {guide}".format(
|
|
name=name.capitalize(),
|
|
guide=desig[event][name].get('guidance'))))
|
|
outFile.write("\n".join(outlines))
|
|
|
|
outFile.write('\n')
|