Merge "Introduce in-tree Rally specs"
This commit is contained in:
commit
f63c4786e1
14
doc/specs/README.rst
Normal file
14
doc/specs/README.rst
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Rally Specs
|
||||||
|
===========
|
||||||
|
|
||||||
|
Specs are detailed description of proposed changes in project. Usually they
|
||||||
|
answer on what, why, how to change in project and who is going to work on
|
||||||
|
change.
|
||||||
|
|
||||||
|
This directory contains 2 subdirectories:
|
||||||
|
|
||||||
|
- in-progress - These specs are approved, but they are not implemented yet
|
||||||
|
- implemented - Implemented specs archive
|
||||||
|
|
||||||
|
If you are looking for full rally road map overview go `here <https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g/edit#gid=0>`_.
|
||||||
|
|
10
doc/specs/implemented/README.rst
Normal file
10
doc/specs/implemented/README.rst
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Rally Specs
|
||||||
|
===========
|
||||||
|
|
||||||
|
Specs are detailed description of proposed changes in project. Usually they
|
||||||
|
answer on what, why, how to change in project and who is going to work on
|
||||||
|
change.
|
||||||
|
|
||||||
|
This directory contains files with implemented specs, 1 file is 1 spec.
|
||||||
|
|
||||||
|
If you are looking for full rally road map overview go `here <https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g/edit#gid=0>`_.
|
12
doc/specs/in-progress/README.rst
Normal file
12
doc/specs/in-progress/README.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Rally Specs
|
||||||
|
===========
|
||||||
|
|
||||||
|
Specs are detailed description of proposed changes in project. Usually they
|
||||||
|
answer on what, why, how to change in project and who is going to work on
|
||||||
|
change.
|
||||||
|
|
||||||
|
|
||||||
|
This directory contains files with accepted by not implemented specs,
|
||||||
|
1 file is 1 spec.
|
||||||
|
|
||||||
|
If you are looking for full rally road map overview go `here <https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g/edit#gid=0>`_.
|
89
doc/specs/template.rst
Normal file
89
doc/specs/template.rst
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
..
|
||||||
|
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
||||||
|
License.
|
||||||
|
|
||||||
|
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||||
|
|
||||||
|
..
|
||||||
|
This template should be in ReSTructured text. The filename in the git
|
||||||
|
repository should match the launchpad URL, for example a URL of
|
||||||
|
https://blueprints.launchpad.net/heat/+spec/awesome-thing should be named
|
||||||
|
awesome-thing.rst . Please do not delete any of the sections in this
|
||||||
|
template. If you have nothing to say for a whole section, just write: None
|
||||||
|
For help with syntax, see http://sphinx-doc.org/rest.html
|
||||||
|
To test out your formatting, see http://www.tele3.cz/jbar/rest/rest.html
|
||||||
|
|
||||||
|
=======================
|
||||||
|
The title of your Spec
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Rally Road map:
|
||||||
|
|
||||||
|
https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g/edit#gid=0
|
||||||
|
|
||||||
|
|
||||||
|
Introduction paragraph -- why are we doing anything?
|
||||||
|
|
||||||
|
Problem description
|
||||||
|
===================
|
||||||
|
|
||||||
|
A detailed description of the problem.
|
||||||
|
|
||||||
|
Proposed change
|
||||||
|
===============
|
||||||
|
|
||||||
|
Here is where you cover the change you propose to make in detail. How do you
|
||||||
|
propose to solve this problem?
|
||||||
|
|
||||||
|
If this is one part of a larger effort make it clear where this piece ends. In
|
||||||
|
other words, what's the scope of this effort?
|
||||||
|
|
||||||
|
Include where in the heat tree hierarchy this will reside.
|
||||||
|
|
||||||
|
Alternatives
|
||||||
|
------------
|
||||||
|
|
||||||
|
This is an optional section, where it does apply we'd just like a demonstration
|
||||||
|
that some thought has been put into why the proposed approach is the best one.
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
|
Assignee(s)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Who is leading the writing of the code? Or is this a blueprint where you're
|
||||||
|
throwing it out there to see who picks it up?
|
||||||
|
|
||||||
|
If more than one person is working on the implementation, please designate the
|
||||||
|
primary author and contact.
|
||||||
|
|
||||||
|
Primary assignee:
|
||||||
|
<launchpad-id or None>
|
||||||
|
|
||||||
|
Can optionally can list additional ids if they intend on doing
|
||||||
|
substantial implementation work on this blueprint.
|
||||||
|
|
||||||
|
Milestones
|
||||||
|
----------
|
||||||
|
|
||||||
|
Target Milestone for completion:
|
||||||
|
Juno-1
|
||||||
|
|
||||||
|
Work Items
|
||||||
|
----------
|
||||||
|
|
||||||
|
Work items or tasks -- break the feature up into the things that need to be
|
||||||
|
done to implement it. Those parts might end up being done by different people,
|
||||||
|
but we're mostly trying to understand the timeline for implementation.
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
|
||||||
|
- Include specific references to specs and/or blueprints in heat, or in other
|
||||||
|
projects, that this one either depends on or is related to.
|
||||||
|
|
||||||
|
- Does this feature require any new library dependencies or code otherwise not
|
||||||
|
included in OpenStack? Or does it depend on a specific version of library?
|
||||||
|
|
119
tests/unit/doc/test_specs.py
Normal file
119
tests/unit/doc/test_specs.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import docutils.core
|
||||||
|
|
||||||
|
from tests.unit import test
|
||||||
|
|
||||||
|
|
||||||
|
class TitlesTestCase(test.TestCase):
|
||||||
|
|
||||||
|
specs_path = os.path.join(
|
||||||
|
os.path.dirname(__file__),
|
||||||
|
os.pardir, os.pardir, os.pardir,
|
||||||
|
"doc", "specs")
|
||||||
|
|
||||||
|
def _get_title(self, section_tree):
|
||||||
|
section = {"subtitles": []}
|
||||||
|
for node in section_tree:
|
||||||
|
if node.tagname == "title":
|
||||||
|
section["name"] = node.rawsource
|
||||||
|
elif node.tagname == "section":
|
||||||
|
subsection = self._get_title(node)
|
||||||
|
section["subtitles"].append(subsection["name"])
|
||||||
|
return section
|
||||||
|
|
||||||
|
def _get_titles(self, spec):
|
||||||
|
titles = {}
|
||||||
|
for node in spec:
|
||||||
|
if node.tagname == "section":
|
||||||
|
# Note subsection subtitles are thrown away
|
||||||
|
section = self._get_title(node)
|
||||||
|
titles[section["name"]] = section["subtitles"]
|
||||||
|
return titles
|
||||||
|
|
||||||
|
def _check_titles(self, filename, expect, actual):
|
||||||
|
missing_sections = [x for x in expect.keys() if x not in actual.keys()]
|
||||||
|
extra_sections = [x for x in actual.keys() if x not in expect.keys()]
|
||||||
|
|
||||||
|
msgs = []
|
||||||
|
if len(missing_sections) > 0:
|
||||||
|
msgs.append("Missing sections: %s" % missing_sections)
|
||||||
|
if len(extra_sections) > 0:
|
||||||
|
msgs.append("Extra sections: %s" % extra_sections)
|
||||||
|
|
||||||
|
for section in expect.keys():
|
||||||
|
missing_subsections = [x for x in expect[section]
|
||||||
|
if x not in actual.get(section, {})]
|
||||||
|
# extra subsections are allowed
|
||||||
|
if len(missing_subsections) > 0:
|
||||||
|
msgs.append("Section '%s' is missing subsections: %s"
|
||||||
|
% (section, missing_subsections))
|
||||||
|
|
||||||
|
if len(msgs) > 0:
|
||||||
|
self.fail("While checking '%s':\n %s"
|
||||||
|
% (filename, "\n ".join(msgs)))
|
||||||
|
|
||||||
|
def _check_lines_wrapping(self, tpl, raw):
|
||||||
|
for i, line in enumerate(raw.split("\n")):
|
||||||
|
if "http://" in line or "https://" in line:
|
||||||
|
continue
|
||||||
|
self.assertTrue(
|
||||||
|
len(line) < 80,
|
||||||
|
msg="%s:%d: Line limited to a maximum of 79 characters." %
|
||||||
|
(tpl, i+1))
|
||||||
|
|
||||||
|
def _check_no_cr(self, tpl, raw):
|
||||||
|
matches = re.findall("\r", raw)
|
||||||
|
self.assertEqual(
|
||||||
|
len(matches), 0,
|
||||||
|
"Found %s literal carriage returns in file %s" %
|
||||||
|
(len(matches), tpl))
|
||||||
|
|
||||||
|
def _check_trailing_spaces(self, tpl, raw):
|
||||||
|
for i, line in enumerate(raw.split("\n")):
|
||||||
|
trailing_spaces = re.findall(" +$", line)
|
||||||
|
self.assertEqual(
|
||||||
|
len(trailing_spaces), 0,
|
||||||
|
"Found trailing spaces on line %s of %s" % (i+1, tpl))
|
||||||
|
|
||||||
|
def test_template(self):
|
||||||
|
with open(os.path.join(self.specs_path, "template.rst")) as f:
|
||||||
|
template = f.read()
|
||||||
|
|
||||||
|
spec = docutils.core.publish_doctree(template)
|
||||||
|
template_titles = self._get_titles(spec)
|
||||||
|
|
||||||
|
for d in ["implemented", "in-progress"]:
|
||||||
|
spec_dir = "%s/%s" % (self.specs_path, d)
|
||||||
|
|
||||||
|
self.assertTrue(os.path.isdir(spec_dir),
|
||||||
|
"%s is not a directory" % spec_dir)
|
||||||
|
for filename in glob.glob(spec_dir + "/*"):
|
||||||
|
if filename.endswith("README.rst"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
filename.endswith(".rst"),
|
||||||
|
"spec's file must have .rst ext. Found: %s" % filename)
|
||||||
|
with open(filename) as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
titles = self._get_titles(docutils.core.publish_doctree(data))
|
||||||
|
self._check_titles(filename, template_titles, titles)
|
||||||
|
self._check_lines_wrapping(filename, data)
|
||||||
|
self._check_no_cr(filename, data)
|
||||||
|
self._check_trailing_spaces(filename, data)
|
@ -97,7 +97,8 @@ class TaskSampleTestCase(test.TestCase):
|
|||||||
inexistent_paths.append(json_path)
|
inexistent_paths.append(json_path)
|
||||||
|
|
||||||
if inexistent_paths:
|
if inexistent_paths:
|
||||||
self.fail("Sample task configs are missing:\n%r" % inexistent_paths)
|
self.fail("Sample task configs are missing:\n%r"
|
||||||
|
% inexistent_paths)
|
||||||
|
|
||||||
def test_task_config_pairs_equality(self):
|
def test_task_config_pairs_equality(self):
|
||||||
for dirname, dirnames, filenames in os.walk(self.samples_path):
|
for dirname, dirnames, filenames in os.walk(self.samples_path):
|
||||||
|
Loading…
Reference in New Issue
Block a user