Remove unit test targets

With the move to zuulv3, the openstack-tox-py* job definitions
ignore doc only changes so we do not get spec
linters run as part of the py27 and py35 targets any more.

Run doc8 from the pep8 target.  Also drop the spell check job
since the way it is implemented causes the doc8 job to fail and
the optional spellcheck job was not useful as a practial quick
check anyways since it reported over 1000 "misspellings" because
OpenStack vocabulary contains many words and acronyms not in its
dictionary.

Corresponding changes have been proposed for nova [1] and
cinder [2].

[1] Ic87e79db6a8881398d670148b609e0b81658dfd1
[2] Ida20764edde3a07c89703d82b41958c96548b239

Change-Id: I3bebbd6107e5bb57eae3af0fa8871760423cb343
This commit is contained in:
liusheng 2017-11-23 11:25:47 +08:00
parent 694346ae1e
commit e738d2bd1a
9 changed files with 128 additions and 283 deletions

View File

@ -3,7 +3,8 @@
# Tempest documentation build configuration file, created by
# sphinx-quickstart on Tue May 21 17:43:32 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
# This file is execfile()d with the current directory set to its containing
# dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
@ -12,26 +13,25 @@
# serve to show the default.
import datetime
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'oslosphinx',
'yasfb',
]
]
# Feed configuration for yasfb
feed_base_url = 'http://specs.openstack.org/openstack/mogan-specs'
@ -46,7 +46,7 @@ templates_path = ['_templates']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
@ -57,13 +57,13 @@ copyright = u'%s, OpenStack Mogan Team' % datetime.date.today().year
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@ -72,11 +72,12 @@ exclude_patterns = [
'**/template.rst',
]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# The reST default role (used for this markup: `text`) to use for all
# documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
@ -92,7 +93,7 @@ pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['mogan-specs.']
# -- Options for HTML output ---------------------------------------------------
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
@ -101,26 +102,26 @@ html_theme = 'nature'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {'incubating': True}
# html_theme_options = {'incubating': True}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# html_favicon = None
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
@ -129,14 +130,14 @@ html_last_updated_fmt = os.popen(git_cmd).read()
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
html_domain_indices = False
@ -145,91 +146,93 @@ html_domain_indices = False
html_use_index = False
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Mogan-Specsdoc'
# -- Options for LaTeX output --------------------------------------------------
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index', 'Mogan-specs.tex', u'Mogan Specs',
u'OpenStack Mogan Team', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# The name of an image file (relative to this directory) to place at the top
# of the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for Texinfo output ------------------------------------------------
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'Mogan-specs', u'Mogan Design Specs',
u'OpenStack Mogan Team', 'mogan-specs', 'Design specifications for the Mogan project.',
u'OpenStack Mogan Team', 'mogan-specs',
'Design specifications for the Mogan project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# -- Options for Epub output ---------------------------------------------------
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'Mogan Specs'
@ -239,34 +242,34 @@ epub_copyright = u'2017, OpenStack Mogan Team'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# epub_cover = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# epub_post_files = []
# A list of files that should not be packed into the epub file.
#epub_exclude_files = []
# epub_exclude_files = []
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
# epub_tocdup = True

View File

@ -112,7 +112,7 @@ REST API impact
* If `Admin` locked an instance, only `Admin` can unlock it.
* If `Owner` locked an instance, both `Owner` and `Admin` can unlock it.
* If an instance has been locked, **UNLOCK** was only allowed for `Owner`
and `Admin`. And, other operations should be denied for non-admin.
and `Admin`. And, other operations should be denied for non-admin.
Security impact
---------------

View File

@ -96,33 +96,33 @@ REST API impact
#. Add a new API that will list manageable servers which will include all
needed informations when calling manage API. It may look like this::
GET v1/manageable_servers
GET v1/manageable_servers
{
"manageable_servers": [
{
"name": "test_server",
"ports": [
{
"address": "a4:dc:be:0e:82:a5",
"uuid": "1ec01153-685a-49b5-a6d3-45a4e7dddf53",
"neutron_port_id": "a9b94592-1d8e-46bb-836b-c7ba935b0136"
},
{
"address": "a4:dc:be:0e:82:a6",
"uuid": "1ec01153-685a-49b5-a6d3-45a4e7dddf54",
"neutron_port_id": "a9b94592-1d8e-46bb-836b-c7ba935b0137"
}
],
"portgroups": [],
"power_state": "power on",
"provision_state": "active",
"uuid": "f978ef48-d4af-4dad-beec-e6174309bc71",
"resource_class": 'gold',
"image_source": "03239419-e588-42b6-a70f-94f23ed0c9e2"
}
]
}
{
"manageable_servers": [
{
"name": "test_server",
"ports": [
{
"address": "a4:dc:be:0e:82:a5",
"uuid": "1ec01153-685a-49b5-a6d3-45a4e7dddf53",
"neutron_port_id": "a9b94592-1d8e-46bb-836b-c7ba935b0136"
},
{
"address": "a4:dc:be:0e:82:a6",
"uuid": "1ec01153-685a-49b5-a6d3-45a4e7dddf54",
"neutron_port_id": "a9b94592-1d8e-46bb-836b-c7ba935b0137"
}
],
"portgroups": [],
"power_state": "power on",
"provision_state": "active",
"uuid": "f978ef48-d4af-4dad-beec-e6174309bc71",
"resource_class": 'gold',
"image_source": "03239419-e588-42b6-a70f-94f23ed0c9e2"
}
]
}
Security impact

View File

@ -36,19 +36,16 @@ Proposed change
===============
* A new mogan.objects.aggregate.Aggregate object would be added to the object
model.
model.
* Add a set of API that only allow admins to create, delete, and list
aggregates, also admins should be able to add nodes to the specific aggregate
and remove nodes from it.
aggregates, also admins should be able to add nodes to the specific aggregate
and remove nodes from it.
* When do resources update we will cache the resource providers and the map of
aggregates with resource providers. Add a node list API for admins which will
derive resource providers from the cache.
aggregates with resource providers. Add a node list API for admins which will
derive resource providers from the cache.
* Before scheduling, mogan will handle the flavor resource_aggregates matching
with node aggregate metadata, then got a list of aggregates, and pass it to
placement with `member_of` parameter when listing resource providers::
with node aggregate metadata, then got a list of aggregates, and pass it to
placement with `member_of` parameter when listing resource providers::
/resource_providers?member_of=in:{agg1_uuid},{agg2_uuid},{agg3_uuid}
@ -145,22 +142,21 @@ REST API impact
PATCH /v1/aggregates/{aggregate_id}
With a body containing the JSON description of the fileds to be updated.
With a body containing the JSON description of the fieds to be updated.
Example Update Aggregate: JSON request::
Example Update Aggregate: JSON request::
[
{
"op": "replace",
"path": "/name",
"value": "foo"
},
{
"op": "add",
"path": "/metadata/k1",
"value": "v1"
}
]
[
{
"op": "replace",
"path": "/name",
"value": "foo"
},
{
"op": "add",
"path": "/metadata/k1",
"value": "v1"
}
]
- To delete an aggregate, a user will ::

View File

@ -2,5 +2,6 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
flake8
doc8 # Apache-2.0

View File

View File

@ -1,32 +0,0 @@
# 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 testtools
class TestDirectories(testtools.TestCase):
def test_directories(self):
releases = [x.split('/')[1] for x in glob.glob('specs/*/')]
for release in releases:
files = os.listdir("specs/%s/" % release)
valid = ['implemented', 'approved']
for name in files:
if name.startswith('.'):
continue
self.assertIn(name, valid,
"Found unexpected file in "
"'specs/%s', specs should be submitted to "
"'specs/%s/approved'" % (release, release))

View File

@ -1,130 +0,0 @@
# 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 re
import docutils.core
import testtools
class TestTitles(testtools.TestCase):
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):
code_block = False
for i, line in enumerate(raw.split("\n")):
# NOTE(ndipanov): Allow code block lines to be longer than 79 ch
if code_block:
if not line or line.startswith(" "):
continue
else:
code_block = False
if "::" in line:
code_block = True
if "http://" in line or "https://" in line:
continue
# Allow lines which do not contain any whitespace
if re.match("\s*[^\s]+$", 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_no_zwsp(self, tpl, raw):
matches = raw.decode('utf-8').find(u"\u200B")
self.assertEqual(
matches, -1,
"Found zero width space characters in file %s" %
(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):
releases = [x.split('/')[1] for x in glob.glob('specs/*/')]
self.assertTrue(len(releases), "Not able to find spec directories")
with open("specs/template.rst") as f:
template = f.read()
spec = docutils.core.publish_doctree(template)
template_titles = self._get_titles(spec)
for release in releases:
files = glob.glob("specs/%s/*/*" % release)
for filename in files:
self.assertTrue(filename.endswith(".rst"),
"spec %s must use 'rst' extension."
% filename)
with open(filename) as f:
data = f.read()
spec = docutils.core.publish_doctree(data)
titles = self._get_titles(spec)
self._check_titles(filename, template_titles, titles)
self._check_lines_wrapping(filename, data)
self._check_no_cr(filename, data)
self._check_no_zwsp(filename, data)
self._check_trailing_spaces(filename, data)

19
tox.ini
View File

@ -1,6 +1,6 @@
[tox]
minversion = 1.6
envlist = py27,docs
minversion = 2.0
envlist = docs, pep8
skipsdist = True
[testenv]
@ -11,12 +11,19 @@ setenv =
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands =
python setup.py testr --slowest --testr-args='{posargs}'
doc8 doc/source README.rst
[testenv:venv]
commands = {posargs}
[testenv:pep8]
commands =
flake8
doc8 --ignore D001 specs/
[testenv:docs]
commands = python setup.py build_sphinx
whitelist_externals = rm
commands =
rm -rf doc/build
python setup.py build_sphinx
# Ignore D001 since we allow lines in excess of 79 characters.
doc8 --ignore D001 --ignore-path .tox --ignore-path .eggs --ignore-path doc/build --ignore-path mogan_specs.egg-info -e txt -e rst