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)
|
||||
|
||||
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):
|
||||
for dirname, dirnames, filenames in os.walk(self.samples_path):
|
||||
|
Loading…
Reference in New Issue
Block a user