diff --git a/.gitignore b/.gitignore index 9652773..1b349fe 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,9 @@ doc/build/ # PyBuilder target/ + +# Files created by releasenotes build +releasenotes/build + +# swap file +*.swp diff --git a/README.md b/README.md deleted file mode 100644 index 348ba23..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -python-senlinclient -=================== - -Client library for OpenStack Clustering Service API diff --git a/README.rst b/README.rst index d1e59a6..01f5550 100644 --- a/README.rst +++ b/README.rst @@ -7,4 +7,4 @@ provides a Python API (the ``senlinclient`` module) and a command-line tool Development takes place via the usual OpenStack processes as outlined in the `developer guide `_. -The master repository is in `Git `_. +The master repository is in `Git `_. diff --git a/doc/source/index.rst b/doc/source/index.rst index 1558c90..d373e69 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -17,6 +17,5 @@ Indices and tables ================== * :ref:`genindex` -* :ref:`modindex` * :ref:`search` diff --git a/senlinclient/osc/__init__.py b/releasenotes/notes/.placeholder similarity index 100% rename from senlinclient/osc/__init__.py rename to releasenotes/notes/.placeholder diff --git a/releasenotes/notes/cluster-scaling-command-e0d96f2cd0c7ca5f.yaml b/releasenotes/notes/cluster-scaling-command-e0d96f2cd0c7ca5f.yaml new file mode 100644 index 0000000..3856593 --- /dev/null +++ b/releasenotes/notes/cluster-scaling-command-e0d96f2cd0c7ca5f.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - OSC commands for cluster scaling are changed from 'cluster scale in' + and 'cluster scale out' to 'cluster shrink' and 'cluster expand' + respectively. diff --git a/releasenotes/notes/node-check-recover-469bf81db9f9f1ec.yaml b/releasenotes/notes/node-check-recover-469bf81db9f9f1ec.yaml new file mode 100644 index 0000000..5bc21a0 --- /dev/null +++ b/releasenotes/notes/node-check-recover-469bf81db9f9f1ec.yaml @@ -0,0 +1,3 @@ +--- +features: + - Added command for node-check and node-recover. diff --git a/senlinclient/osc/v1/__init__.py b/releasenotes/source/_static/.placeholder similarity index 100% rename from senlinclient/osc/v1/__init__.py rename to releasenotes/source/_static/.placeholder diff --git a/senlinclient/tests/unit/osc/__init__.py b/releasenotes/source/_templates/.placeholder similarity index 100% rename from senlinclient/tests/unit/osc/__init__.py rename to releasenotes/source/_templates/.placeholder diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py new file mode 100644 index 0000000..5a2629f --- /dev/null +++ b/releasenotes/source/conf.py @@ -0,0 +1,277 @@ +# -*- coding: utf-8 -*- +# 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. + +# Senlin Release Notes documentation build configuration file, created by +# sphinx-quickstart on Tue Nov 3 17:40:50 2015. +# +# 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. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# 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('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# 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. +extensions = [ + 'oslosphinx', + 'reno.sphinxext', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Senlin Client Release Notes' +copyright = u'2015, Senlin Developers' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +import pbr.version +senlin_version = pbr.version.VersionInfo('python-muranoclient') +# The full version, including alpha/beta/rc tags. +release = senlin_version.version_string_with_vcs() +# The short X.Y version. +version = senlin_version.canonical_version_string() + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# 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 + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# 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 = {} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# 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 + +# 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 + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'SenlinClientReleaseNotesdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + + # 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, or own class]). +latex_documents = [ + ('index', 'SenlinClientReleaseNotes.tex', + u'Senlin Client Release Notes Documentation', + u'Senlin Developers', 'manual'), +] + +# 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 + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'senlinclientreleasenotes', + u'Senlin Client Release Notes Documentation', + [u'Senlin Developers'], 1) +] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- 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', 'SenlinClientReleaseNotes', + u'Senlin Client Release Notes Documentation', + u'Senlin Developers', 'SenlinClientReleaseNotes', + 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst new file mode 100644 index 0000000..72aa37f --- /dev/null +++ b/releasenotes/source/index.rst @@ -0,0 +1,8 @@ +============================= +Senlin Client Release Notes +============================= + +.. toctree:: + :maxdepth: 1 + + unreleased diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst new file mode 100644 index 0000000..cd22aab --- /dev/null +++ b/releasenotes/source/unreleased.rst @@ -0,0 +1,5 @@ +============================== + Current Series Release Notes +============================== + +.. release-notes:: diff --git a/requirements.txt b/requirements.txt index 1b408d1..e0318fe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,16 +2,16 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -Babel>=1.3 # BSD +Babel>=2.3.4 # BSD pbr>=1.6 # Apache-2.0 cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0 PrettyTable<0.8,>=0.7 # BSD -openstacksdk>=0.8.1 # Apache-2.0 +openstacksdk>=0.8.6 # Apache-2.0 oslo.i18n>=2.1.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0 -oslo.utils>=3.5.0 # Apache-2.0 -python-heatclient>=0.6.0 # Apache-2.0 +oslo.utils>=3.11.0 # Apache-2.0 +python-heatclient>=1.1.0 # Apache-2.0 python-openstackclient>=2.1.0 # Apache-2.0 PyYAML>=3.1.0 # MIT -requests!=2.9.0,>=2.8.1 # Apache-2.0 +requests>=2.10.0 # Apache-2.0 six>=1.9.0 # MIT diff --git a/senlinclient/common/exc.py b/senlinclient/common/exc.py index e5e0a6a..7712283 100644 --- a/senlinclient/common/exc.py +++ b/senlinclient/common/exc.py @@ -230,7 +230,7 @@ _EXCEPTION_MAP = { def parse_exception(exc): """Parse exception code and yield useful information. - :param details: details of the exception. + :param exc: details of the exception. """ if isinstance(exc, sdkexc.HttpException): if exc.details is None: diff --git a/senlinclient/common/sdk.py b/senlinclient/common/sdk.py index e853926..65caead 100644 --- a/senlinclient/common/sdk.py +++ b/senlinclient/common/sdk.py @@ -27,9 +27,9 @@ prop = base.prop class ProfileAction(argparse.Action): - """A custom action to parse user proferences as key=value pairs + """A custom action to parse user preferences as key=value pairs - Stores results in users proferences object. + Stores results in users preferences object. """ prof = profile.Profile() @@ -124,6 +124,15 @@ class Resource(base.Resource): def create_connection(prof=None, user_agent=None, **kwargs): + if not prof: + prof = profile.Profile() + interface = kwargs.pop('interface', None) + region_name = kwargs.pop('region_name', None) + if interface: + prof.set_interface('clustering', interface) + if region_name: + prof.set_region('clustering', region_name) + try: conn = connection.Connection(profile=prof, user_agent=user_agent, **kwargs) diff --git a/senlinclient/osc/plugin.py b/senlinclient/plugin.py similarity index 100% rename from senlinclient/osc/plugin.py rename to senlinclient/plugin.py diff --git a/senlinclient/tests/unit/osc/v1/__init__.py b/senlinclient/tests/unit/osc/v1/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/senlinclient/tests/unit/osc/v1/fakes.py b/senlinclient/tests/unit/osc/v1/fakes.py deleted file mode 100644 index 19a8363..0000000 --- a/senlinclient/tests/unit/osc/v1/fakes.py +++ /dev/null @@ -1,33 +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 mock - -from openstackclient.tests import utils -from senlinclient.tests.unit.osc import fakes - - -class FakeClusteringv1Client(object): - def __init__(self, **kwargs): - self.http_client = mock.Mock() - self.http_client.auth_token = kwargs['token'] - self.profiles = fakes.FakeResource(None, {}) - - -class TestClusteringv1(utils.TestCommand): - def setUp(self): - super(TestClusteringv1, self).setUp() - - self.app.client_manager.clustering = FakeClusteringv1Client( - token=fakes.AUTH_TOKEN, - auth_url=fakes.AUTH_URL - ) diff --git a/senlinclient/tests/unit/test_sdk.py b/senlinclient/tests/unit/test_sdk.py index 3654a19..dbbb0ce 100644 --- a/senlinclient/tests/unit/test_sdk.py +++ b/senlinclient/tests/unit/test_sdk.py @@ -14,6 +14,9 @@ import mock import os import testtools +from openstack import connection as sdk_connection +from openstack import profile as sdk_profile + from senlinclient.common import sdk @@ -54,3 +57,47 @@ class TestSdk(testtools.TestCase): mock_prof.ALL = 'mock_prof.ALL' sdk.ProfileAction.set_option('interface', 'test=val1') mock_prof.set_interface.assert_called_once_with('test', 'val1') + + @mock.patch.object(sdk_connection, 'Connection') + def test_create_connection_with_profile(self, mock_connection): + mock_prof = mock.Mock() + mock_conn = mock.Mock() + mock_connection.return_value = mock_conn + kwargs = { + 'user_id': '123', + 'password': 'abc', + 'auth_url': 'test_url' + } + res = sdk.create_connection(mock_prof, **kwargs) + mock_connection.assert_called_once_with(profile=mock_prof, + user_agent=None, + user_id='123', + password='abc', + auth_url='test_url') + self.assertEqual(mock_conn, res) + + @mock.patch.object(sdk_connection, 'Connection') + @mock.patch.object(sdk_profile, 'Profile') + def test_create_connection_without_profile(self, mock_profile, + mock_connection): + mock_prof = mock.Mock() + mock_conn = mock.Mock() + mock_profile.return_value = mock_prof + mock_connection.return_value = mock_conn + kwargs = { + 'interface': 'public', + 'region_name': 'RegionOne', + 'user_id': '123', + 'password': 'abc', + 'auth_url': 'test_url' + } + res = sdk.create_connection(**kwargs) + + mock_prof.set_interface.assert_called_once_with('clustering', 'public') + mock_prof.set_region.assert_called_once_with('clustering', 'RegionOne') + mock_connection.assert_called_once_with(profile=mock_prof, + user_agent=None, + user_id='123', + password='abc', + auth_url='test_url') + self.assertEqual(mock_conn, res) diff --git a/senlinclient/tests/unit/osc/fakes.py b/senlinclient/tests/unit/v1/fakes.py similarity index 89% rename from senlinclient/tests/unit/osc/fakes.py rename to senlinclient/tests/unit/v1/fakes.py index f6d4718..d591454 100644 --- a/senlinclient/tests/unit/osc/fakes.py +++ b/senlinclient/tests/unit/v1/fakes.py @@ -11,10 +11,13 @@ # under the License. import json +import mock import requests import six import sys +from openstackclient.tests import utils + AUTH_TOKEN = "foobar" AUTH_URL = "http://0.0.0.0" @@ -158,3 +161,19 @@ class FakeResponse(requests.Response): self._content = json.dumps(data) if not isinstance(self._content, six.binary_type): self._content = self._content.encode() + + +class FakeClusteringv1Client(object): + def __init__(self, **kwargs): + self.http_client = mock.Mock() + self.http_client.auth_token = kwargs['token'] + self.profiles = FakeResource(None, {}) + + +class TestClusteringv1(utils.TestCommand): + def setUp(self): + super(TestClusteringv1, self).setUp() + + self.app.client_manager.clustering = FakeClusteringv1Client( + token=AUTH_TOKEN, auth_url=AUTH_URL + ) diff --git a/senlinclient/tests/unit/osc/v1/test_action.py b/senlinclient/tests/unit/v1/test_action.py similarity index 98% rename from senlinclient/tests/unit/osc/v1/test_action.py rename to senlinclient/tests/unit/v1/test_action.py index f2df79a..21927dc 100644 --- a/senlinclient/tests/unit/osc/v1/test_action.py +++ b/senlinclient/tests/unit/v1/test_action.py @@ -17,8 +17,8 @@ from openstack.cluster.v1 import action as sdk_action from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import action as osc_action -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import action as osc_action class TestAction(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_build_info.py b/senlinclient/tests/unit/v1/test_build_info.py similarity index 92% rename from senlinclient/tests/unit/osc/v1/test_build_info.py rename to senlinclient/tests/unit/v1/test_build_info.py index 1bf8e58..ba78774 100644 --- a/senlinclient/tests/unit/osc/v1/test_build_info.py +++ b/senlinclient/tests/unit/v1/test_build_info.py @@ -14,8 +14,8 @@ import mock from openstack.cluster.v1 import build_info as sdk_build_info -from senlinclient.osc.v1 import build_info as osc_build_info -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import build_info as osc_build_info class TestBuildInfo(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_cluster.py b/senlinclient/tests/unit/v1/test_cluster.py similarity index 99% rename from senlinclient/tests/unit/osc/v1/test_cluster.py rename to senlinclient/tests/unit/v1/test_cluster.py index 093417d..6495ea0 100644 --- a/senlinclient/tests/unit/osc/v1/test_cluster.py +++ b/senlinclient/tests/unit/v1/test_cluster.py @@ -18,8 +18,8 @@ from openstack.cluster.v1 import cluster as sdk_cluster from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import cluster as osc_cluster -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import cluster as osc_cluster class TestCluster(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_cluster_policy.py b/senlinclient/tests/unit/v1/test_cluster_policy.py similarity index 97% rename from senlinclient/tests/unit/osc/v1/test_cluster_policy.py rename to senlinclient/tests/unit/v1/test_cluster_policy.py index 2d3d3cf..c034552 100644 --- a/senlinclient/tests/unit/osc/v1/test_cluster_policy.py +++ b/senlinclient/tests/unit/v1/test_cluster_policy.py @@ -14,8 +14,8 @@ import mock from openstack.cluster.v1 import cluster_policy as sdk_cluster_policy -from senlinclient.osc.v1 import cluster_policy as osc_cluster_policy -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import cluster_policy as osc_cluster_policy class TestClusterPolicy(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_event.py b/senlinclient/tests/unit/v1/test_event.py similarity index 98% rename from senlinclient/tests/unit/osc/v1/test_event.py rename to senlinclient/tests/unit/v1/test_event.py index 06eb434..7cd2f6a 100644 --- a/senlinclient/tests/unit/osc/v1/test_event.py +++ b/senlinclient/tests/unit/v1/test_event.py @@ -17,8 +17,8 @@ from openstack.cluster.v1 import event as sdk_event from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import event as osc_event -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import event as osc_event class TestEvent(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_node.py b/senlinclient/tests/unit/v1/test_node.py similarity index 87% rename from senlinclient/tests/unit/osc/v1/test_node.py rename to senlinclient/tests/unit/v1/test_node.py index b7c84c0..6bfdada 100644 --- a/senlinclient/tests/unit/osc/v1/test_node.py +++ b/senlinclient/tests/unit/v1/test_node.py @@ -18,8 +18,8 @@ from openstack.cluster.v1 import node as sdk_node from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import node as osc_node -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import node as osc_node class TestNode(fakes.TestClusteringv1): @@ -402,3 +402,57 @@ class TestNodeDelete(TestNode): mock_stdin.readline.assert_called_with() self.mock_client.delete_node.assert_not_called() + + +class TestNodeCheck(TestNode): + response = {"action": "8bb476c3-0f4c-44ee-9f64-c7b0260814de"} + + def setUp(self): + super(TestNodeCheck, self).setUp() + self.cmd = osc_node.CheckNode(self.app, None) + self.mock_client.check_node = mock.Mock( + return_value=self.response) + + def test_node_check(self): + arglist = ['node1', 'node2', 'node3'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.check_node.assert_has_calls( + [mock.call('node1'), mock.call('node2'), + mock.call('node3')] + ) + + def test_node_check_not_found(self): + arglist = ['node1'] + self.mock_client.check_node.side_effect = sdk_exc.ResourceNotFound + parsed_args = self.check_parser(self.cmd, arglist, []) + error = self.assertRaises(exc.CommandError, self.cmd.take_action, + parsed_args) + self.assertIn('Node not found: node1', str(error)) + + +class TestNodeRecover(TestNode): + response = {"action": "8bb476c3-0f4c-44ee-9f64-c7b0260814de"} + + def setUp(self): + super(TestNodeRecover, self).setUp() + self.cmd = osc_node.RecoverNode(self.app, None) + self.mock_client.recover_node = mock.Mock( + return_value=self.response) + + def test_node_recover(self): + arglist = ['node1', 'node2', 'node3'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.recover_node.assert_has_calls( + [mock.call('node1'), mock.call('node2'), + mock.call('node3')] + ) + + def test_node_recover_not_found(self): + arglist = ['node1'] + self.mock_client.recover_node.side_effect = sdk_exc.ResourceNotFound + parsed_args = self.check_parser(self.cmd, arglist, []) + error = self.assertRaises(exc.CommandError, self.cmd.take_action, + parsed_args) + self.assertIn('Node not found: node1', str(error)) diff --git a/senlinclient/tests/unit/osc/v1/test_policy.py b/senlinclient/tests/unit/v1/test_policy.py similarity index 99% rename from senlinclient/tests/unit/osc/v1/test_policy.py rename to senlinclient/tests/unit/v1/test_policy.py index c6920de..350a7d9 100644 --- a/senlinclient/tests/unit/osc/v1/test_policy.py +++ b/senlinclient/tests/unit/v1/test_policy.py @@ -18,8 +18,8 @@ from openstack.cluster.v1 import policy as sdk_policy from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import policy as osc_policy -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import policy as osc_policy class TestPolicy(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_policy_type.py b/senlinclient/tests/unit/v1/test_policy_type.py similarity index 96% rename from senlinclient/tests/unit/osc/v1/test_policy_type.py rename to senlinclient/tests/unit/v1/test_policy_type.py index 84506f7..956dc16 100644 --- a/senlinclient/tests/unit/osc/v1/test_policy_type.py +++ b/senlinclient/tests/unit/v1/test_policy_type.py @@ -16,8 +16,8 @@ from openstack.cluster.v1 import policy_type as sdk_policy_type from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import policy_type as osc_policy_type -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import policy_type as osc_policy_type class TestPolicyType(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_profile.py b/senlinclient/tests/unit/v1/test_profile.py similarity index 99% rename from senlinclient/tests/unit/osc/v1/test_profile.py rename to senlinclient/tests/unit/v1/test_profile.py index b81d1ed..d84e0d0 100644 --- a/senlinclient/tests/unit/osc/v1/test_profile.py +++ b/senlinclient/tests/unit/v1/test_profile.py @@ -19,8 +19,8 @@ from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc from openstackclient.common import utils -from senlinclient.osc.v1 import profile as osc_profile -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import profile as osc_profile class TestProfile(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_profile_type.py b/senlinclient/tests/unit/v1/test_profile_type.py similarity index 96% rename from senlinclient/tests/unit/osc/v1/test_profile_type.py rename to senlinclient/tests/unit/v1/test_profile_type.py index 9826d16..5a1fa0f 100644 --- a/senlinclient/tests/unit/osc/v1/test_profile_type.py +++ b/senlinclient/tests/unit/v1/test_profile_type.py @@ -16,8 +16,8 @@ from openstack.cluster.v1 import profile_type as sdk_profile_type from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import profile_type as osc_profile_type -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import profile_type as osc_profile_type class TestProfileType(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/osc/v1/test_receiver.py b/senlinclient/tests/unit/v1/test_receiver.py similarity index 99% rename from senlinclient/tests/unit/osc/v1/test_receiver.py rename to senlinclient/tests/unit/v1/test_receiver.py index 98fed37..053bdc7 100644 --- a/senlinclient/tests/unit/osc/v1/test_receiver.py +++ b/senlinclient/tests/unit/v1/test_receiver.py @@ -18,8 +18,8 @@ from openstack.cluster.v1 import receiver as sdk_receiver from openstack import exceptions as sdk_exc from openstackclient.common import exceptions as exc -from senlinclient.osc.v1 import receiver as osc_receiver -from senlinclient.tests.unit.osc.v1 import fakes +from senlinclient.tests.unit.v1 import fakes +from senlinclient.v1 import receiver as osc_receiver class TestReceiver(fakes.TestClusteringv1): diff --git a/senlinclient/tests/unit/v1/test_shell.py b/senlinclient/tests/unit/v1/test_shell.py index 01b19bd..e2d1ef2 100644 --- a/senlinclient/tests/unit/v1/test_shell.py +++ b/senlinclient/tests/unit/v1/test_shell.py @@ -16,6 +16,7 @@ import six import testtools from openstack import exceptions as oexc +from oslotest import mockpatch from senlinclient.common import exc from senlinclient.common.i18n import _ from senlinclient.common import utils @@ -39,6 +40,13 @@ class ShellTest(testtools.TestCase): 'template': {"Template": "data"} } } + self.patch('senlinclient.v1.shell.show_deprecated') + + # NOTE(pshchelo): this overrides the testtools.TestCase.patch method + # that does simple monkey-patching in favor of mock's patching + def patch(self, target, **kwargs): + mockfixture = self.useFixture(mockpatch.Patch(target, **kwargs)) + return mockfixture.mock def _make_args(self, args): """Convert a dict to an object.""" diff --git a/senlinclient/osc/v1/action.py b/senlinclient/v1/action.py similarity index 100% rename from senlinclient/osc/v1/action.py rename to senlinclient/v1/action.py diff --git a/senlinclient/osc/v1/build_info.py b/senlinclient/v1/build_info.py similarity index 100% rename from senlinclient/osc/v1/build_info.py rename to senlinclient/v1/build_info.py diff --git a/senlinclient/v1/client.py b/senlinclient/v1/client.py index 334f1d9..4667fa9 100644 --- a/senlinclient/v1/client.py +++ b/senlinclient/v1/client.py @@ -27,139 +27,376 @@ class Client(object): ###################################################################### def profile_types(self, **query): + """List profile types + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #listProfileTypes + """ return self.service.profile_types(**query) def get_profile_type(self, profile_type): + """Show profile type details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showProfileType + """ return self.service.get_profile_type(profile_type) def profiles(self, **query): + """List profiles + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#listProfiles + """ return self.service.profiles(**query) def create_profile(self, **attrs): + """Create a profile + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#createProfile + """ return self.service.create_profile(**attrs) def get_profile(self, profile): + """Show profile details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showProfile + """ return self.service.get_profile(profile) def update_profile(self, profile, **attrs): + """Update a profile + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#updateProfile + """ return self.service.update_profile(profile, **attrs) def delete_profile(self, profile, ignore_missing=True): + """Delete a profile + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#deleteProfile + """ return self.service.delete_profile(profile, ignore_missing) def policy_types(self, **query): + """List policy types + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #listPolicyType + """ return self.service.policy_types(**query) def get_policy_type(self, policy_type): + """Show policy type details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #showPolicyType + """ return self.service.get_policy_type(policy_type) def policies(self, **query): + """List policies + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#listPolicies + """ return self.service.policies(**query) def create_policy(self, **attrs): + """Create a policy + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#createPolicy + """ return self.service.create_policy(**attrs) def get_policy(self, policy): + """Show policy details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showPolicy + """ return self.service.get_policy(policy) def update_policy(self, policy, **attrs): + """Update policy + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#updatePolicy + """ return self.service.update_policy(policy, **attrs) def delete_policy(self, policy, ignore_missing=True): + """Delete policy + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#deletePolicy + """ return self.service.delete_policy(policy, ignore_missing) def clusters(self, **queries): + """List clusters + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#listClusters + """ return self.service.clusters(**queries) def create_cluster(self, **attrs): + """Create a cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#createCluster + """ return self.service.create_cluster(**attrs) def get_cluster(self, cluster): + """Show cluster details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showCluster + """ return self.service.get_cluster(cluster) def update_cluster(self, cluster, **attrs): + """Update cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#updateCluster + """ return self.service.update_cluster(cluster, **attrs) def delete_cluster(self, cluster, ignore_missing=True): + """Delete cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#deleteCluster + """ return self.service.delete_cluster(cluster, ignore_missing) def cluster_add_nodes(self, cluster, nodes): + """Add a node to cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_add_nodes(cluster, nodes) def cluster_del_nodes(self, cluster, nodes): + """Delete a node belongs to cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_del_nodes(cluster, nodes) def cluster_resize(self, cluster, **params): + """Resize cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_resize(cluster, **params) def cluster_scale_out(self, cluster, count): + """Scale out cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_scale_out(cluster, count) def cluster_scale_in(self, cluster, count): + """Scale in cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_scale_in(cluster, count) def cluster_policies(self, cluster, **queries): + """List all policies attached to cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #listClusterPolicies + """ return self.service.cluster_policies(cluster, **queries) def get_cluster_policy(self, policy, cluster): + """Show details of a policy attached to cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #showClusterPolicy + """ return self.service.get_cluster_policy(policy, cluster) def cluster_attach_policy(self, cluster, policy, **attrs): + """Attach a policy to cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_attach_policy(cluster, policy, **attrs) def cluster_detach_policy(self, cluster, policy): + """Detach a policy from cluster + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_detach_policy(cluster, policy) def cluster_update_policy(self, cluster, policy, **attrs): + """Update the policy attachment + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.cluster_update_policy(cluster, policy, **attrs) def check_cluster(self, cluster, **params): + """Check cluster's health status + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.check_cluster(cluster, **params) def recover_cluster(self, cluster, **params): + """Recover cluster from failure state + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#clusterAction + """ return self.service.recover_cluster(cluster, **params) def nodes(self, **queries): + """List nodes + + Doc link: http://developer.openstack.org/api-ref-clustering-v1.html + #listNodes + """ return self.service.nodes(**queries) def create_node(self, **attrs): + """Create a node + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#createNode + """ return self.service.create_node(**attrs) def get_node(self, node, args=None): + """Show node details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showNode + """ return self.service.get_node(node, args=args) def update_node(self, node, **attrs): + """Update node + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#updateNode + """ return self.service.update_node(node, **attrs) def delete_node(self, node, ignore_missing=True): + """Delete node + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#deleteNode + """ return self.service.delete_node(node, ignore_missing) def check_node(self, node, **params): + """Check node's health status + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#nodeAction + """ return self.service.check_node(node, **params) def recover_node(self, node, **params): + """Recover node from failure state + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#nodeAction + """ return self.service.recover_node(node, **params) def receivers(self, **queries): + """List receivers + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#listReceivers + """ return self.service.receivers(**queries) def create_receiver(self, **attrs): + """Creare a receiver + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #createReceiver + """ return self.service.create_receiver(**attrs) def get_receiver(self, receiver): + """Show receiver details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showReceiver + """ return self.service.get_receiver(receiver) def delete_receiver(self, receiver, ignore_missing=True): + """Delete receiver + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html + #deleteReceiver + """ return self.service.delete_receiver(receiver, ignore_missing) def events(self, **queries): + """List events + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#listEvents + """ return self.service.events(**queries) def get_event(self, event): + """Show event details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showEvent + """ return self.service.get_event(event) def actions(self, **queries): + """List actions + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#listActions + """ return self.service.actions(**queries) def get_action(self, action): + """Show action details + + Doc link: + http://developer.openstack.org/api-ref-clustering-v1.html#showAction + """ return self.service.get_action(action) diff --git a/senlinclient/osc/v1/cluster.py b/senlinclient/v1/cluster.py similarity index 100% rename from senlinclient/osc/v1/cluster.py rename to senlinclient/v1/cluster.py diff --git a/senlinclient/osc/v1/cluster_policy.py b/senlinclient/v1/cluster_policy.py similarity index 100% rename from senlinclient/osc/v1/cluster_policy.py rename to senlinclient/v1/cluster_policy.py diff --git a/senlinclient/osc/v1/event.py b/senlinclient/v1/event.py similarity index 100% rename from senlinclient/osc/v1/event.py rename to senlinclient/v1/event.py diff --git a/senlinclient/osc/v1/node.py b/senlinclient/v1/node.py similarity index 85% rename from senlinclient/osc/v1/node.py rename to senlinclient/v1/node.py index 387af28..9e2ac63 100644 --- a/senlinclient/osc/v1/node.py +++ b/senlinclient/v1/node.py @@ -332,3 +332,57 @@ class DeleteNode(command.Command): {'count': failure_count, 'total': len(parsed_args.node)}) print('Request accepted') + + +class CheckNode(command.Command): + """Check the node(s).""" + log = logging.getLogger(__name__ + ".CheckNode") + + def get_parser(self, prog_name): + parser = super(CheckNode, self).get_parser(prog_name) + parser.add_argument( + 'node', + metavar='', + nargs='+', + help=_('ID or name of node(s) to check.') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + senlin_client = self.app.client_manager.clustering + for nid in parsed_args.node: + try: + resp = senlin_client.check_node(nid) + except sdk_exc.ResourceNotFound: + raise exc.CommandError(_('Node not found: %s') % nid) + print('Node check request on node %(nid)s is accepted by ' + 'action %(action)s.' + % {'nid': nid, 'action': resp['action']}) + + +class RecoverNode(command.Command): + """Recover the node(s).""" + log = logging.getLogger(__name__ + ".RecoverNode") + + def get_parser(self, prog_name): + parser = super(RecoverNode, self).get_parser(prog_name) + parser.add_argument( + 'node', + metavar='', + nargs='+', + help=_('ID or name of node(s) to recover.') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + senlin_client = self.app.client_manager.clustering + for nid in parsed_args.node: + try: + resp = senlin_client.recover_node(nid) + except sdk_exc.ResourceNotFound: + raise exc.CommandError(_('Node not found: %s') % nid) + print('Node recover request on node %(nid)s is accepted by ' + 'action %(action)s.' + % {'nid': nid, 'action': resp['action']}) diff --git a/senlinclient/osc/v1/policy.py b/senlinclient/v1/policy.py similarity index 100% rename from senlinclient/osc/v1/policy.py rename to senlinclient/v1/policy.py diff --git a/senlinclient/osc/v1/policy_type.py b/senlinclient/v1/policy_type.py similarity index 100% rename from senlinclient/osc/v1/policy_type.py rename to senlinclient/v1/policy_type.py diff --git a/senlinclient/osc/v1/profile.py b/senlinclient/v1/profile.py similarity index 100% rename from senlinclient/osc/v1/profile.py rename to senlinclient/v1/profile.py diff --git a/senlinclient/osc/v1/profile_type.py b/senlinclient/v1/profile_type.py similarity index 100% rename from senlinclient/osc/v1/profile_type.py rename to senlinclient/v1/profile_type.py diff --git a/senlinclient/osc/v1/receiver.py b/senlinclient/v1/receiver.py similarity index 100% rename from senlinclient/osc/v1/receiver.py rename to senlinclient/v1/receiver.py diff --git a/senlinclient/v1/shell.py b/senlinclient/v1/shell.py index 95ea120..6ef78e3 100644 --- a/senlinclient/v1/shell.py +++ b/senlinclient/v1/shell.py @@ -15,17 +15,27 @@ import logging from openstack import exceptions as sdk_exc from senlinclient.common import exc from senlinclient.common.i18n import _ +from senlinclient.common.i18n import _LW from senlinclient.common import utils logger = logging.getLogger(__name__) +def show_deprecated(deprecated, recommended): + logger.warning(_LW('"%(old)s" is deprecated, ' + 'please use "%(new)s" instead.'), + {'old': deprecated, + 'new': recommended} + ) + + def do_build_info(service, args=None): """Retrieve build information. :param sc: Instance of senlinclient. :param args: Additional command line arguments, if any. """ + show_deprecated('senlin build-info', 'openstack cluster build info') result = service.get_build_info() formatters = { @@ -44,6 +54,8 @@ def do_profile_type_list(service, args=None): :param sc: Instance of senlinclient. :param args: Additional command line arguments, if any. """ + show_deprecated('senlin profile-type-list', + 'openstack cluster profile type list') types = service.profile_types() utils.print_list(types, ['name'], sortby_index=0) @@ -56,6 +68,8 @@ def do_profile_type_list(service, args=None): % ', '.join(utils.supported_formats.keys())) def do_profile_type_show(service, args): """Get the details about a profile type.""" + show_deprecated('senlin profile-type-show', + 'openstack cluster profile type show') try: res = service.get_profile_type(args.type_name) except sdk_exc.ResourceNotFound: @@ -83,8 +97,8 @@ def do_profile_type_show(service, args): help=_('Only return profiles that appear after the given ID.')) @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-g', '--global-project', default=False, action="store_true", help=_('Indicate that the list should include profiles from' ' all projects. This option is subject to access policy ' @@ -93,6 +107,7 @@ def do_profile_type_show(service, args): help=_('Print full IDs in list.')) def do_profile_list(service, args=None): """List profiles that meet the criteria.""" + show_deprecated('senlin profile-list', 'openstack cluster profile list') fields = ['id', 'name', 'type', 'created_at'] queries = { 'limit': args.limit, @@ -143,7 +158,8 @@ def _show_profile(service, profile_id): help=_('Name of the profile to create.')) def do_profile_create(service, args): """Create a profile.""" - + show_deprecated('senlin profile-create', + 'openstack cluster profile create') spec = utils.get_spec_content(args.spec_file) type_name = spec.get('type', None) type_version = spec.get('version', None) @@ -173,6 +189,7 @@ def do_profile_create(service, args): help=_('Name or ID of profile to show.')) def do_profile_show(service, args): """Show the profile details.""" + show_deprecated('senlin profile-show', 'openstack cluster profile show') _show_profile(service, args.id) @@ -187,6 +204,8 @@ def do_profile_show(service, args): help=_('Name or ID of the profile to update.')) def do_profile_update(service, args): """Update a profile.""" + show_deprecated('senlin profile-update', + 'openstack cluster profile update') params = { 'name': args.name, } @@ -206,6 +225,8 @@ def do_profile_update(service, args): help=_('Name or ID of profile(s) to delete.')) def do_profile_delete(service, args): """Delete profile(s).""" + show_deprecated('senlin profile-delete', + 'openstack cluster profile delete') failure_count = 0 for pid in args.id: @@ -225,6 +246,8 @@ def do_profile_delete(service, args): def do_policy_type_list(service, args): """List the available policy types.""" + show_deprecated('senlin policy-type-list', + 'openstack cluster policy type list') types = service.policy_types() utils.print_list(types, ['name'], sortby_index=0) @@ -237,6 +260,8 @@ def do_policy_type_list(service, args): % ', '.join(utils.supported_formats.keys())) def do_policy_type_show(service, args): """Get the details about a policy type.""" + show_deprecated('senlin policy-type-show', + 'openstack cluster policy type show') try: res = service.get_policy_type(args.type_name) except sdk_exc.ResourceNotFound: @@ -262,8 +287,8 @@ def do_policy_type_show(service, args): help=_('Only return policies that appear after the given ID.')) @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-g', '--global-project', default=False, action="store_true", help=_('Indicate that the list should include policies from' ' all projects. This option is subject to access policy ' @@ -272,6 +297,7 @@ def do_policy_type_show(service, args): help=_('Print full IDs in list.')) def do_policy_list(service, args=None): """List policies that meet the criteria.""" + show_deprecated('senlin policy-list', 'openstack cluster policy list') fields = ['id', 'name', 'type', 'created_at'] queries = { 'limit': args.limit, @@ -312,6 +338,7 @@ def _show_policy(service, policy_id): help=_('Name of the policy to create.')) def do_policy_create(service, args): """Create a policy.""" + show_deprecated('senlin policy-create', 'openstack cluster policy create') spec = utils.get_spec_content(args.spec_file) attrs = { 'name': args.name, @@ -326,6 +353,7 @@ def do_policy_create(service, args): help=_('Name of the policy to be updated.')) def do_policy_show(service, args): """Show the policy details.""" + show_deprecated('senlin policy-show', 'openstack cluster policy show') _show_policy(service, policy_id=args.id) @@ -335,6 +363,7 @@ def do_policy_show(service, args): help=_('Name of the policy to be updated.')) def do_policy_update(service, args): """Update a policy.""" + show_deprecated('senlin policy-update', 'openstack cluster policy update') params = { 'name': args.name, } @@ -349,6 +378,7 @@ def do_policy_update(service, args): help=_('Name or ID of policy(s) to delete.')) def do_policy_delete(service, args): """Delete policy(s).""" + show_deprecated('senlin policy-delete', 'openstack cluster policy delete') failure_count = 0 for pid in args.id: @@ -373,8 +403,8 @@ def do_policy_delete(service, args): action='append') @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-l', '--limit', metavar='', help=_('Limit the number of clusters returned.')) @utils.arg('-m', '--marker', metavar='', @@ -388,6 +418,7 @@ def do_policy_delete(service, args): help=_('Print full IDs in list.')) def do_cluster_list(service, args=None): """List the user's clusters.""" + show_deprecated('senlin cluster-list', 'openstack cluster list') fields = ['id', 'name', 'status', 'created_at', 'updated_at'] queries = { 'limit': args.limit, @@ -443,6 +474,7 @@ def _show_cluster(service, cluster_id): help=_('Name of the cluster to create.')) def do_cluster_create(service, args): """Create the cluster.""" + show_deprecated('senlin cluster-create', 'openstack cluster create') if args.min_size and not args.desired_capacity: args.desired_capacity = args.min_size attrs = { @@ -463,6 +495,7 @@ def do_cluster_create(service, args): help=_('Name or ID of cluster(s) to delete.')) def do_cluster_delete(service, args): """Delete the cluster(s).""" + show_deprecated('senlin cluster-delete', 'openstack cluster delete') failure_count = 0 for cid in args.id: @@ -492,6 +525,7 @@ def do_cluster_delete(service, args): help=_('Name or ID of cluster to be updated.')) def do_cluster_update(service, args): """Update the cluster.""" + show_deprecated('senlin cluster-update', 'openstack cluster update') cluster = service.get_cluster(args.id) attrs = { 'name': args.name, @@ -508,6 +542,7 @@ def do_cluster_update(service, args): help=_('Name or ID of cluster to show.')) def do_cluster_show(service, args): """Show details of the cluster.""" + show_deprecated('senlin cluster-show', 'openstack cluster show') _show_cluster(service, args.id) @@ -526,7 +561,8 @@ def do_cluster_show(service, args): help=_('Name or ID of cluster to nodes from.')) def do_cluster_node_list(service, args): """List nodes from cluster.""" - + show_deprecated('senlin cluster-node-list', + 'openstack cluster node members list') queries = { 'cluster_id': args.id, 'limit': args.limit, @@ -555,6 +591,8 @@ def do_cluster_node_list(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_node_add(service, args): """Add specified nodes to cluster.""" + show_deprecated('senlin cluster-node-add', + 'openstack cluster node members add') node_ids = args.nodes.split(',') resp = service.cluster_add_nodes(args.id, node_ids) print('Request accepted by action: %s' % resp['action']) @@ -567,6 +605,8 @@ def do_cluster_node_add(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_node_del(service, args): """Delete specified nodes from cluster.""" + show_deprecated('senlin cluster-node-del', + 'openstack cluster node members del') node_ids = args.nodes.split(',') resp = service.cluster_del_nodes(args.id, node_ids) print('Request accepted by action: %s' % resp['action']) @@ -599,7 +639,7 @@ def do_cluster_resize(service, args): """Resize a cluster.""" # validate parameters # NOTE: this will be much simpler if cliutils supports exclusive groups - + show_deprecated('senlin cluster-resize', 'openstack cluster resize') action_args = {} capacity = args.capacity @@ -672,6 +712,7 @@ def do_cluster_resize(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_scale_out(service, args): """Scale out a cluster by the specified number of nodes.""" + show_deprecated('senlin cluster-scale-out', 'openstack cluster scale out') resp = service.cluster_scale_out(args.id, args.count) print('Request accepted by action %s' % resp['action']) @@ -682,6 +723,7 @@ def do_cluster_scale_out(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_scale_in(service, args): """Scale in a cluster by the specified number of nodes.""" + show_deprecated('senlin cluster-scale-in', 'openstack cluster scale in') resp = service.cluster_scale_in(args.id, args.count) print('Request accepted by action %s' % resp['action']) @@ -693,14 +735,16 @@ def do_cluster_scale_in(service, args): action='append') @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-F', '--full-id', default=False, action="store_true", help=_('Print full IDs in list.')) @utils.arg('id', metavar='', help=_('Name or ID of cluster to query on.')) def do_cluster_policy_list(service, args): """List policies from cluster.""" + show_deprecated('senlin cluster-policy-list', + 'openstack cluster policy binding list') fields = ['policy_id', 'policy_name', 'policy_type', 'enabled'] cluster = service.get_cluster(args.id) @@ -729,6 +773,8 @@ def do_cluster_policy_list(service, args): help=_('ID or name of the cluster to query on.')) def do_cluster_policy_show(service, args): """Show a specific policy that is bound to the specified cluster.""" + show_deprecated('senlin cluster-policy-show', + 'openstack cluster policy binding show') binding = service.get_cluster_policy(args.policy, args.id) utils.print_dict(binding.to_dict()) @@ -742,6 +788,8 @@ def do_cluster_policy_show(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_policy_attach(service, args): """Attach policy to cluster.""" + show_deprecated('senlin cluster-policy-attach', + 'openstack cluster policy attach') kwargs = { 'enabled': args.enabled, } @@ -756,6 +804,8 @@ def do_cluster_policy_attach(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_policy_detach(service, args): """Detach policy from cluster.""" + show_deprecated('senlin cluster-policy-detach', + 'openstack cluster policy detach') resp = service.cluster_detach_policy(args.id, args.policy) print('Request accepted by action %s' % resp['action']) @@ -768,6 +818,8 @@ def do_cluster_policy_detach(service, args): help=_('Name or ID of cluster to operate on.')) def do_cluster_policy_update(service, args): """Update a policy's properties on a cluster.""" + show_deprecated('senlin cluster-policy-update', + 'openstack cluster policy binding update') kwargs = { 'enabled': args.enabled, } @@ -780,6 +832,7 @@ def do_cluster_policy_update(service, args): help=_('ID or name of cluster(s) to operate on.')) def do_cluster_check(service, args): """Check the cluster(s).""" + show_deprecated('senlin cluster-check', 'openstack cluster check') for cid in args.id: resp = service.check_cluster(cid) print('Cluster check request on cluster %(cid)s is accepted by ' @@ -790,6 +843,7 @@ def do_cluster_check(service, args): help=_('ID or name of cluster(s) to operate on.')) def do_cluster_recover(service, args): """Recover the cluster(s).""" + show_deprecated('senlin cluster-recover', 'openstack cluster recover') for cid in args.id: resp = service.recover_cluster(cid) print('Cluster recover request on cluster %(cid)s is accepted by ' @@ -808,8 +862,8 @@ def do_cluster_recover(service, args): action='append') @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-l', '--limit', metavar='', help=_('Limit the number of nodes returned.')) @utils.arg('-m', '--marker', metavar='', @@ -822,6 +876,7 @@ def do_cluster_recover(service, args): help=_('Print full IDs in list.')) def do_node_list(service, args): """Show list of nodes.""" + show_deprecated('senlin node-list', 'openstack cluster node list') fields = ['id', 'name', 'index', 'status', 'cluster_id', 'physical_id', 'profile_name', 'created_at', 'updated_at'] @@ -855,7 +910,6 @@ def do_node_list(service, args): def _show_node(service, node_id, show_details=False): """Show detailed info about the specified node.""" - args = {'show_details': True} if show_details else None try: node = service.get_node(node_id, args=args) @@ -889,6 +943,7 @@ def _show_node(service, node_id, show_details=False): help=_('Name of the node to create.')) def do_node_create(service, args): """Create the node.""" + show_deprecated('senlin node-create', 'openstack cluster node create') attrs = { 'name': args.name, 'cluster_id': args.cluster, @@ -907,6 +962,7 @@ def do_node_create(service, args): help=_('Name or ID of the node to show the details for.')) def do_node_show(service, args): """Show detailed info about the specified node.""" + show_deprecated('senlin node-show', 'openstack cluster node show') _show_node(service, args.id, args.details) @@ -914,6 +970,7 @@ def do_node_show(service, args): help=_('Name or ID of node(s) to delete.')) def do_node_delete(service, args): """Delete the node(s).""" + show_deprecated('senlin node-delete', 'openstack cluster node delete') failure_count = 0 for nid in args.id: @@ -943,6 +1000,7 @@ def do_node_delete(service, args): help=_('Name or ID of node to update.')) def do_node_update(service, args): """Update the node.""" + show_deprecated('senlin node-update', 'openstack cluster node update') # Find the node first, we need its UUID try: node = service.get_node(args.id) @@ -964,6 +1022,7 @@ def do_node_update(service, args): help=_('ID of node(s) to check.')) def do_node_check(service, args): """Check the node(s).""" + show_deprecated('senlin node-check', 'openstack cluster node check') failure_count = 0 for nid in args.id: @@ -982,6 +1041,7 @@ def do_node_check(service, args): help=_('ID of node(s) to recover.')) def do_node_recover(service, args): """Recover the node(s).""" + show_deprecated('senlin node-recover', 'openstack cluster node recover') failure_count = 0 for nid in args.id: @@ -1010,8 +1070,8 @@ def do_node_recover(service, args): help=_('Only return receivers that appear after the given ID.')) @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-g', '--global-project', default=False, action="store_true", help=_('Indicate that the list should include receivers from' ' all projects. This option is subject to access policy ' @@ -1020,6 +1080,7 @@ def do_node_recover(service, args): help=_('Print full IDs in list.')) def do_receiver_list(service, args): """List receivers that meet the criteria.""" + show_deprecated('senlin receiver-list', 'openstack cluster receiver list') fields = ['id', 'name', 'type', 'cluster_id', 'action', 'created_at'] queries = { 'limit': args.limit, @@ -1063,6 +1124,7 @@ def _show_receiver(service, receiver_id): help=_('Name or ID of the receiver to show.')) def do_receiver_show(service, args): """Show the receiver details.""" + show_deprecated('senlin receiver-show', 'openstack cluster receiver show') _show_receiver(service, receiver_id=args.id) @@ -1080,6 +1142,8 @@ def do_receiver_show(service, args): help=_('Name of the receiver to create.')) def do_receiver_create(service, args): """Create a receiver.""" + show_deprecated('senlin receiver-create', + 'openstack cluster receiver create') params = { 'name': args.name, @@ -1097,6 +1161,8 @@ def do_receiver_create(service, args): help=_('Name or ID of receiver(s) to delete.')) def do_receiver_delete(service, args): """Delete receiver(s).""" + show_deprecated('senlin receiver-delete', + 'openstack cluster receiver delete') failure_count = 0 for wid in args.id: @@ -1125,8 +1191,8 @@ def do_receiver_delete(service, args): help=_('Only return events that appear after the given event ID.')) @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-g', '--global-project', default=False, action="store_true", help=_('Whether events from all projects should be listed. ' ' Default to False. Setting this to True may demand ' @@ -1135,7 +1201,7 @@ def do_receiver_delete(service, args): help=_('Print full IDs in list.')) def do_event_list(service, args): """List events.""" - + show_deprecated('senlin event-list', 'openstack cluster event list') fields = ['id', 'timestamp', 'obj_type', 'obj_id', 'obj_name', 'action', 'status', 'status_reason', 'level'] queries = { @@ -1161,6 +1227,7 @@ def do_event_list(service, args): help=_('ID of event to display details for.')) def do_event_show(service, args): """Describe the event.""" + show_deprecated('senlin event-show', 'openstack cluster event show') try: event = service.get_event(args.id) except sdk_exc.ResourceNotFound: @@ -1179,8 +1246,8 @@ def do_event_show(service, args): action='append') @utils.arg('-o', '--sort', metavar='', help=_('Sorting option which is a string containing a list of keys ' - 'separated by commas. Each key can be optionally appened by ' - 'a sort direction (:asc or :desc)')) + 'separated by commas. Each key can be optionally appended ' + 'by a sort direction (:asc or :desc)')) @utils.arg('-l', '--limit', metavar='', help=_('Limit the number of actions returned.')) @utils.arg('-m', '--marker', metavar='', @@ -1189,7 +1256,7 @@ def do_event_show(service, args): help=_('Print full IDs in list.')) def do_action_list(service, args): """List actions.""" - + show_deprecated('senlin action-list', 'openstack cluster action list') fields = ['id', 'name', 'action', 'status', 'target', 'depends_on', 'depended_by', 'created_at'] @@ -1229,6 +1296,7 @@ def do_action_list(service, args): help=_('Name or ID of the action to show the details for.')) def do_action_show(service, args): """Show detailed info about the specified action.""" + show_deprecated('senlin action-show', 'openstack cluster action show') try: action = service.get_action(args.id) except sdk_exc.ResourceNotFound: diff --git a/setup.cfg b/setup.cfg index 6836168..3f4141c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,55 +27,57 @@ console_scripts = senlin = senlinclient.shell:main openstack.cli.extension = - clustering = senlinclient.osc.plugin + clustering = senlinclient.plugin openstack.clustering.v1 = - cluster_action_list = senlinclient.osc.v1.action:ListAction - cluster_action_show = senlinclient.osc.v1.action:ShowAction - cluster_build_info = senlinclient.osc.v1.build_info:BuildInfo - cluster_check = senlinclient.osc.v1.cluster:CheckCluster - cluster_create = senlinclient.osc.v1.cluster:CreateCluster - cluster_delete = senlinclient.osc.v1.cluster:DeleteCluster - cluster_event_list = senlinclient.osc.v1.event:ListEvent - cluster_event_show = senlinclient.osc.v1.event:ShowEvent - cluster_list = senlinclient.osc.v1.cluster:ListCluster - cluster_members_list = senlinclient.osc.v1.cluster:ClusterNodeList - cluster_members_add = senlinclient.osc.v1.cluster:ClusterNodeAdd - cluster_members_del = senlinclient.osc.v1.cluster:ClusterNodeDel - cluster_node_create = senlinclient.osc.v1.node:CreateNode - cluster_node_delete = senlinclient.osc.v1.node:DeleteNode - cluster_node_list = senlinclient.osc.v1.node:ListNode - cluster_node_show = senlinclient.osc.v1.node:ShowNode - cluster_node_update = senlinclient.osc.v1.node:UpdateNode - cluster_policy_attach = senlinclient.osc.v1.cluster:ClusterPolicyAttach - cluster_policy_binding_list = senlinclient.osc.v1.cluster_policy:ClusterPolicyList - cluster_policy_binding_show = senlinclient.osc.v1.cluster_policy:ClusterPolicyShow - cluster_policy_binding_update = senlinclient.osc.v1.cluster_policy:ClusterPolicyUpdate - cluster_policy_create = senlinclient.osc.v1.policy:CreatePolicy - cluster_policy_delete = senlinclient.osc.v1.policy:DeletePolicy - cluster_policy_detach = senlinclient.osc.v1.cluster:ClusterPolicyDetach - cluster_policy_list = senlinclient.osc.v1.policy:ListPolicy - cluster_policy_show = senlinclient.osc.v1.policy:ShowPolicy - cluster_policy_type_list = senlinclient.osc.v1.policy_type:PolicyTypeList - cluster_policy_type_show = senlinclient.osc.v1.policy_type:PolicyTypeShow - cluster_policy_update = senlinclient.osc.v1.policy:UpdatePolicy - cluster_profile_create = senlinclient.osc.v1.profile:CreateProfile - cluster_profile_delete = senlinclient.osc.v1.profile:DeleteProfile - cluster_profile_list = senlinclient.osc.v1.profile:ListProfile - cluster_profile_show = senlinclient.osc.v1.profile:ShowProfile - cluster_profile_type_list = senlinclient.osc.v1.profile_type:ProfileTypeList - cluster_profile_type_show = senlinclient.osc.v1.profile_type:ProfileTypeShow - cluster_profile_update = senlinclient.osc.v1.profile:UpdateProfile - cluster_receiver_create = senlinclient.osc.v1.receiver:CreateReceiver - cluster_receiver_delete = senlinclient.osc.v1.receiver:DeleteReceiver - cluster_receiver_list = senlinclient.osc.v1.receiver:ListReceiver - cluster_receiver_show = senlinclient.osc.v1.receiver:ShowReceiver - cluster_recover = senlinclient.osc.v1.cluster:RecoverCluster - cluster_resize = senlinclient.osc.v1.cluster:ResizeCluster - cluster_scale_in = senlinclient.osc.v1.cluster:ScaleInCluster - cluster_scale_out = senlinclient.osc.v1.cluster:ScaleOutCluster - cluster_show = senlinclient.osc.v1.cluster:ShowCluster - cluster_update = senlinclient.osc.v1.cluster:UpdateCluster + cluster_action_list = senlinclient.v1.action:ListAction + cluster_action_show = senlinclient.v1.action:ShowAction + cluster_build_info = senlinclient.v1.build_info:BuildInfo + cluster_check = senlinclient.v1.cluster:CheckCluster + cluster_create = senlinclient.v1.cluster:CreateCluster + cluster_delete = senlinclient.v1.cluster:DeleteCluster + cluster_event_list = senlinclient.v1.event:ListEvent + cluster_event_show = senlinclient.v1.event:ShowEvent + cluster_list = senlinclient.v1.cluster:ListCluster + cluster_members_list = senlinclient.v1.cluster:ClusterNodeList + cluster_members_add = senlinclient.v1.cluster:ClusterNodeAdd + cluster_members_del = senlinclient.v1.cluster:ClusterNodeDel + cluster_node_check = senlinclient.v1.node:CheckNode + cluster_node_create = senlinclient.v1.node:CreateNode + cluster_node_delete = senlinclient.v1.node:DeleteNode + cluster_node_list = senlinclient.v1.node:ListNode + cluster_node_recover = senlinclient.v1.node:RecoverNode + cluster_node_show = senlinclient.v1.node:ShowNode + cluster_node_update = senlinclient.v1.node:UpdateNode + cluster_policy_attach = senlinclient.v1.cluster:ClusterPolicyAttach + cluster_policy_binding_list = senlinclient.v1.cluster_policy:ClusterPolicyList + cluster_policy_binding_show = senlinclient.v1.cluster_policy:ClusterPolicyShow + cluster_policy_binding_update = senlinclient.v1.cluster_policy:ClusterPolicyUpdate + cluster_policy_create = senlinclient.v1.policy:CreatePolicy + cluster_policy_delete = senlinclient.v1.policy:DeletePolicy + cluster_policy_detach = senlinclient.v1.cluster:ClusterPolicyDetach + cluster_policy_list = senlinclient.v1.policy:ListPolicy + cluster_policy_show = senlinclient.v1.policy:ShowPolicy + cluster_policy_type_list = senlinclient.v1.policy_type:PolicyTypeList + cluster_policy_type_show = senlinclient.v1.policy_type:PolicyTypeShow + cluster_policy_update = senlinclient.v1.policy:UpdatePolicy + cluster_profile_create = senlinclient.v1.profile:CreateProfile + cluster_profile_delete = senlinclient.v1.profile:DeleteProfile + cluster_profile_list = senlinclient.v1.profile:ListProfile + cluster_profile_show = senlinclient.v1.profile:ShowProfile + cluster_profile_type_list = senlinclient.v1.profile_type:ProfileTypeList + cluster_profile_type_show = senlinclient.v1.profile_type:ProfileTypeShow + cluster_profile_update = senlinclient.v1.profile:UpdateProfile + cluster_receiver_create = senlinclient.v1.receiver:CreateReceiver + cluster_receiver_delete = senlinclient.v1.receiver:DeleteReceiver + cluster_receiver_list = senlinclient.v1.receiver:ListReceiver + cluster_receiver_show = senlinclient.v1.receiver:ShowReceiver + cluster_recover = senlinclient.v1.cluster:RecoverCluster + cluster_resize = senlinclient.v1.cluster:ResizeCluster + cluster_shrink = senlinclient.v1.cluster:ScaleInCluster + cluster_expand = senlinclient.v1.cluster:ScaleOutCluster + cluster_show = senlinclient.v1.cluster:ShowCluster + cluster_update = senlinclient.v1.cluster:UpdateCluster [global] setup-hooks = diff --git a/test-requirements.txt b/test-requirements.txt index fcf1a68..c2cf2a4 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -6,9 +6,9 @@ hacking<0.11,>=0.10.0 coverage>=3.6 # Apache-2.0 discover # BSD -fixtures>=1.3.1 # Apache-2.0/BSD +fixtures>=3.0.0 # Apache-2.0/BSD requests-mock>=0.7.0 # Apache-2.0 -mock>=1.2 # BSD +mock>=2.0 # BSD mox3>=0.7.0 # Apache-2.0 oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 oslotest>=1.10.0 # Apache-2.0 @@ -16,3 +16,4 @@ sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD testrepository>=0.0.18 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=1.4.0 # MIT +reno>=1.6.2 # Apache2 diff --git a/tools/senlinrc b/tools/senlinrc index 1fae0e8..59e898e 100644 --- a/tools/senlinrc +++ b/tools/senlinrc @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# IMPORTANT: Cleanse existing environment varible first +# IMPORTANT: Cleanse existing environment variable first unset OS_USERNAME unset OS_PASSWORD unset OS_REGION_NAME diff --git a/tox.ini b/tox.ini index 312bc0c..23c94bb 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py34,py27,pypy,pep8 +envlist = py34,py27,pypy,pep8,releasenotes minversion = 1.6 skipsdist = True @@ -31,6 +31,9 @@ commands = python setup.py testr --coverage --testr-args='{posargs}' commands= python setup.py build_sphinx +[testenv:releasenotes] +commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html + [flake8] show-source = True exclude=.venv,.git,.tox,dist,*openstack/common*,*lib/python*,*egg,build