Merge "[docs] fix invalid "rst" usage"
This commit is contained in:
commit
a3d647087d
@ -39,16 +39,19 @@ class HeatDataplane(context.Context):
|
||||
|
||||
This context will create stacks by given template for each tenant and
|
||||
add details to context. Following details will be added:
|
||||
id of stack;
|
||||
template file contents;
|
||||
files dictionary;
|
||||
stack parameters;
|
||||
|
||||
* id of stack;
|
||||
* template file contents;
|
||||
* files dictionary;
|
||||
* stack parameters;
|
||||
|
||||
Heat template should define a "gate" node which will interact with Rally
|
||||
by ssh and workload nodes by any protocol. To make this possible heat
|
||||
template should accept the following parameters:
|
||||
network_id: id of public network
|
||||
router_id: id of external router to connect "gate" node
|
||||
key_name: name of nova ssh keypair to use for "gate" node
|
||||
|
||||
* network_id: id of public network
|
||||
* router_id: id of external router to connect "gate" node
|
||||
* key_name: name of nova ssh keypair to use for "gate" node
|
||||
"""
|
||||
FILE_SCHEMA = {
|
||||
"description": "",
|
||||
|
@ -27,8 +27,9 @@ class FaultInjectionHook(hook.Hook):
|
||||
"""Performs fault injection using os-faults library.
|
||||
|
||||
Configuration:
|
||||
action - string that represents an action (more info in [1])
|
||||
verify - whether to verify connection to cloud nodes or not
|
||||
|
||||
* action - string that represents an action (more info in [1])
|
||||
* verify - whether to verify connection to cloud nodes or not
|
||||
|
||||
This plugin discovers extra config of ExistingCloud
|
||||
and looks for "cloud_config" field. If cloud_config is present then
|
||||
|
@ -171,10 +171,12 @@ class CreateAlarmAndGetHistory(ceiloutils.CeilometerScenario):
|
||||
def run(self, meter_name, threshold, state, timeout=60, **kwargs):
|
||||
"""Create an alarm, get and set the state and get the alarm history.
|
||||
|
||||
This scenario makes following queries:
|
||||
GET /v2/alarms/{alarm_id}/history
|
||||
GET /v2/alarms/{alarm_id}/state
|
||||
PUT /v2/alarms/{alarm_id}/state
|
||||
This scenario makes following queries:
|
||||
|
||||
* GET /v2/alarms/{alarm_id}/history
|
||||
* GET /v2/alarms/{alarm_id}/state
|
||||
* PUT /v2/alarms/{alarm_id}/state
|
||||
|
||||
Initially alarm is created and then get the state of the created alarm
|
||||
using its alarm_id. Then get the history of the alarm. And finally the
|
||||
state of the alarm is updated using given state. meter_name and
|
||||
|
@ -139,8 +139,8 @@ class CreateVolumeTypeAndEncryptionType(cinder_utils.CinderBasic):
|
||||
is_public=True):
|
||||
"""Create encryption type
|
||||
|
||||
This scenario first creates a volume type, then creates an encryption
|
||||
type for the volume type.
|
||||
This scenario first creates a volume type, then creates an encryption
|
||||
type for the volume type.
|
||||
|
||||
:param create_specs: The encryption type specifications to add.
|
||||
DEPRECATED, specify arguments explicitly.
|
||||
@ -186,9 +186,9 @@ class CreateAndListEncryptionType(cinder_utils.CinderBasic):
|
||||
key_size=None, control_location="front-end", search_opts=None):
|
||||
"""Create and list encryption type
|
||||
|
||||
This scenario firstly creates a volume type, secondly creates an
|
||||
encryption type for the volume type, thirdly lists all encryption
|
||||
types.
|
||||
This scenario firstly creates a volume type, secondly creates an
|
||||
encryption type for the volume type, thirdly lists all encryption
|
||||
types.
|
||||
|
||||
:param create_specs: The encryption type specifications to add.
|
||||
DEPRECATED, specify arguments explicitly.
|
||||
@ -254,10 +254,10 @@ class CreateGetAndDeleteEncryptionType(cinder_utils.CinderBasic):
|
||||
key_size=None, control_location="front-end"):
|
||||
"""Create get and delete an encryption type
|
||||
|
||||
This scenario firstly creates an encryption type for a volome
|
||||
type created in the context, then gets detailed information of
|
||||
the created encryption type, finally deletes the created
|
||||
encryption type.
|
||||
This scenario firstly creates an encryption type for a volome
|
||||
type created in the context, then gets detailed information of
|
||||
the created encryption type, finally deletes the created
|
||||
encryption type.
|
||||
|
||||
:param provider: The class that provides encryption support. For
|
||||
example, LuksEncryptor.
|
||||
@ -295,8 +295,8 @@ class CreateAndDeleteEncryptionType(cinder_utils.CinderBasic):
|
||||
key_size=None, control_location="front-end"):
|
||||
"""Create and delete encryption type
|
||||
|
||||
This scenario firstly creates an encryption type for a given
|
||||
volume type, then deletes the created encryption type.
|
||||
This scenario firstly creates an encryption type for a given
|
||||
volume type, then deletes the created encryption type.
|
||||
|
||||
:param create_specs: the encryption type specifications to add
|
||||
:param provider: The class that provides encryption support. For
|
||||
@ -340,9 +340,9 @@ class CreateAndUpdateEncryptionType(cinder_utils.CinderBasic):
|
||||
update_key_size=None, update_control_location=None):
|
||||
"""Create and update encryption type
|
||||
|
||||
This scenario firstly creates a volume type, secondly creates an
|
||||
encryption type for the volume type, thirdly updates the encryption
|
||||
type.
|
||||
This scenario firstly creates a volume type, secondly creates an
|
||||
encryption type for the volume type, thirdly updates the encryption
|
||||
type.
|
||||
|
||||
:param create_provider: The class that provides encryption support. For
|
||||
example, LuksEncryptor.
|
||||
@ -391,8 +391,8 @@ class CreateVolumeTypeAddAndListTypeAccess(scenario.OpenStackScenario):
|
||||
def run(self, description=None, is_public=False):
|
||||
"""Add and list volume type access for the given project.
|
||||
|
||||
This scenario first creates a private volume type, then add project
|
||||
access and list project access to it.
|
||||
This scenario first creates a private volume type, then add project
|
||||
access and list project access to it.
|
||||
|
||||
:param description: Description of the volume type
|
||||
:param is_public: Volume type visibility
|
||||
|
@ -757,8 +757,9 @@ class CreateVolumeAndClone(cinder_utils.CinderBasic):
|
||||
def run(self, size, image=None, nested_level=1, **kwargs):
|
||||
"""Create a volume, then clone it to another volume.
|
||||
|
||||
This creates a volume, then clone it to anothor volume,
|
||||
and then clone the new volume to next volume...
|
||||
This creates a volume, then clone it to anothor volume,
|
||||
and then clone the new volume to next volume...
|
||||
|
||||
1. create source volume (from image)
|
||||
2. clone source volume to volume1
|
||||
3. clone volume1 to volume2
|
||||
|
@ -85,10 +85,11 @@ class BootAndDeleteServerWithKeypair(utils.NovaScenario):
|
||||
"""Boot and delete server with keypair.
|
||||
|
||||
Plan of this scenario:
|
||||
- create a keypair
|
||||
- boot a VM with created keypair
|
||||
- delete server
|
||||
- delete keypair
|
||||
|
||||
- create a keypair
|
||||
- boot a VM with created keypair
|
||||
- delete server
|
||||
- delete keypair
|
||||
|
||||
:param image: ID of the image to be used for server creation
|
||||
:param flavor: ID of the flavor to be used for server creation
|
||||
|
@ -46,7 +46,7 @@ class ValidCommandValidator(validators.FileExistsValidator):
|
||||
"""Checks that parameter is a proper command-specifying dictionary.
|
||||
|
||||
Ensure that the command dictionary is a proper command-specifying
|
||||
dictionary described in `vmtasks.VMTasks.boot_runcommand_delete'
|
||||
dictionary described in 'vmtasks.VMTasks.boot_runcommand_delete'
|
||||
docstring.
|
||||
|
||||
:param param_name: Name of parameter to validate
|
||||
@ -500,7 +500,7 @@ class DDLoadTest(BootRuncommandDelete):
|
||||
max_log_length=None, **kwargs):
|
||||
"""Boot a server from a custom image and performs dd load test.
|
||||
|
||||
NOTE: dd load test is prepared script by Rally team. It checks
|
||||
.. note:: dd load test is prepared script by Rally team. It checks
|
||||
writing and reading metrics from the VM.
|
||||
|
||||
:param image: glance image name to use for the vm. Optional
|
||||
|
@ -49,15 +49,15 @@ class TempestManager(testr.TestrLauncher):
|
||||
|
||||
Rally supports features listed below:
|
||||
|
||||
* *cloning Tempest*: repository and version can be specified
|
||||
* *installation*: system-wide with checking existence of required
|
||||
packages or in virtual environment
|
||||
* *configuration*: options are discovered via OpenStack API, but you can
|
||||
override them if you need
|
||||
* *running*: pre-creating all required resources(i.e images, tenants,
|
||||
etc), prepare arguments, launching Tempest, live-progress output
|
||||
* *results*: all verifications are stored in db, you can built reports,
|
||||
compare verification at whatever you want time.
|
||||
* *cloning Tempest*: repository and version can be specified
|
||||
* *installation*: system-wide with checking existence of required
|
||||
packages or in virtual environment
|
||||
* *configuration*: options are discovered via OpenStack API, but you can
|
||||
override them if you need
|
||||
* *running*: pre-creating all required resources(i.e images, tenants,
|
||||
etc), prepare arguments, launching Tempest, live-progress output
|
||||
* *results*: all verifications are stored in db, you can built reports,
|
||||
compare verification at whatever you want time.
|
||||
|
||||
Appeared in Rally 0.8.0 *(actually, it appeared long time ago with first
|
||||
revision of Verification Component, but 0.8.0 is mentioned since it is
|
||||
|
@ -13,7 +13,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from rally.common.plugin import info
|
||||
from docutils import frontend
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from docutils import utils
|
||||
|
||||
from rally.common.plugin import plugin
|
||||
from rally.common import validation
|
||||
from rally import plugins
|
||||
@ -21,6 +25,15 @@ from rally.task import scenario
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
def _parse_rst(text):
|
||||
parser = rst.Parser()
|
||||
settings = frontend.OptionParser(
|
||||
components=(rst.Parser,)).get_default_values()
|
||||
document = utils.new_document(text, settings)
|
||||
parser.parse(text, document)
|
||||
return document.children
|
||||
|
||||
|
||||
class DocstringsTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -47,20 +60,50 @@ class DocstringsTestCase(test.TestCase):
|
||||
result.append(msg)
|
||||
return result
|
||||
|
||||
# the list with plugins names which use rst definitions in their docstrings
|
||||
_HAS_VALID_DEFINITIONS = []
|
||||
|
||||
def _validate_rst(self, plugin_name, text, msg_buffer):
|
||||
# need to wait till the next release of rally
|
||||
return
|
||||
parsed_docstring = _parse_rst(text)
|
||||
for item in parsed_docstring:
|
||||
if (isinstance(item, nodes.definition_list)
|
||||
and plugin_name not in self._HAS_VALID_DEFINITIONS):
|
||||
msg_buffer.append("Plugin %s has a docstring with invalid "
|
||||
"format. Re-check intend and required empty "
|
||||
"lines between the list title and list "
|
||||
"items." % plugin_name)
|
||||
elif isinstance(item, nodes.system_message):
|
||||
msg_buffer.append(
|
||||
"A warning is caught while parsing docstring of '%s' "
|
||||
"plugin: %s" % (plugin_name, item.astext()))
|
||||
|
||||
def _check_docstrings(self, msg_buffer):
|
||||
for plg_cls in plugin.Plugin.get_all():
|
||||
if plg_cls.__module__.startswith("rally."):
|
||||
doc = info.parse_docstring(plg_cls.__doc__)
|
||||
short_description = doc["short_description"]
|
||||
if short_description.startswith("Test"):
|
||||
msg_buffer.append("One-line description for %s"
|
||||
" should be declarative and not"
|
||||
" start with 'Test(s) ...'"
|
||||
% plg_cls.__name__)
|
||||
if not plg_cls.get_info()["title"]:
|
||||
msg = "Class '{}.{}' should have a docstring."
|
||||
msg_buffer.append(msg.format(plg_cls.__module__,
|
||||
plg_cls.__name__))
|
||||
if not plg_cls.__module__.startswith("rally_openstack."):
|
||||
continue
|
||||
name = "%s (%s.%s)" % (plg_cls.get_name(),
|
||||
plg_cls.__module__,
|
||||
plg_cls.__name__)
|
||||
doc_info = plg_cls.get_info()
|
||||
if not doc_info["title"]:
|
||||
msg_buffer.append("Plugin '%s' should have a docstring."
|
||||
% name)
|
||||
if doc_info["title"].startswith("Test"):
|
||||
msg_buffer.append("One-line description for %s"
|
||||
" should be declarative and not"
|
||||
" start with 'Test(s) ...'"
|
||||
% name)
|
||||
|
||||
# NOTE(andreykurilin): I never saw any real usage of
|
||||
# reStructuredText definitions in our docstrings. In most cases,
|
||||
# "definitions" means that there is an issue with intends or
|
||||
# missed empty line before the list title and list items.
|
||||
if doc_info["description"]:
|
||||
self._validate_rst(plg_cls.get_name(),
|
||||
doc_info["description"],
|
||||
msg_buffer)
|
||||
|
||||
def _check_described_params(self, msg_buffer):
|
||||
for plg_cls in plugin.Plugin.get_all():
|
||||
@ -81,4 +124,4 @@ class DocstringsTestCase(test.TestCase):
|
||||
|
||||
self._check_described_params(msg_buffer)
|
||||
if msg_buffer:
|
||||
self.fail("\n%s" % "\n".join(msg_buffer))
|
||||
self.fail("\n%s" % "\n===============\n".join(msg_buffer))
|
||||
|
Loading…
Reference in New Issue
Block a user