Compare commits

..

13 Commits

Author SHA1 Message Date
Zuul
f4b1a3f224 Merge "Add support for v2/rating/modules endpoints" 2020-02-10 10:16:26 +00:00
Luka Peschke
9424e67f21 [ussuri][goal] Drop python 2.7 support and testing
This drops python2.7 support for cloudkittyclient. Even if this should be
done between milestone-1 and milestone-2, zuul jobs running on python2 are
currently broken since nova dropped python2.7 support.

Depends-On: https://review.opendev.org/#/c/693631/
Change-Id: I7615601540419e45259291a7bfce1cc038c27986
2020-01-23 13:42:35 +00:00
Luka Peschke
9c3bd770f2 Fix tox environments
Work items:

* Removed the globale-requirements constraint. Since python-cloudkittyclient
  is now part of the global requirements, the upstream requirements
  file can't be used anymore.

* Add cliff to docs requirements.

* Change cloudkittyclient namespace names: Having a dot in a namespace
  name causes the "autoprogram-cliff" to use the "application mode".

Change-Id: I8020d816b3397550fbcbd42cc14a9861bca7ae80
2019-12-17 15:10:17 +01:00
Luka Peschke
d28c5bc4dd Improve HTTP error formatting
This improves formatting for HTTP errors. keystoneauth's HttpErrors
are now caught an re-formatted to include the body of the http response.

Work items:

* Introduce the "http_error_formatter" function decorator, which catches
  an re-formats keystoneauths HttpErrors.

* Introduce the "format_http_errors" class decorator, which applies the
  "http_error_formatter" to all functions of a class.

* Add an "HttpDecoratorMeta" to the "BaseManager" class. This will decorate
  all functions of classes inheriting from "BaseManager" with the
  "http_error_formatter" decorator.

Change-Id: I6735f1fa8d876a87e2b7d4aaa533d5a32b085735
2019-11-28 11:52:40 +01:00
caoyuan
3e7f7a0f5d tox: Keeping going with docs
Sphinx 1.8 introduced [1] the '--keep-going' argument which, as its name
suggests, keeps the build running when it encounters non-fatal errors.
This is exceptionally useful in avoiding a continuous edit-build loop
when undertaking large doc reworks where multiple errors may be
introduced.

[1] https://github.com/sphinx-doc/sphinx/commit/e3483e9b045

Change-Id: Ie373018aafc05f7ea859a73c55163840dee60b56
2019-11-18 15:46:25 +00:00
Luka Peschke
584046761a Adapt functional tests to python3
A test looking for a regex in an argparse error message is failing when ran
on python3. Since this is now the default python runtime for devstack-based
jobs, this updates the message.

Change-Id: Id3372998715f13f7641d11a4a1d9d16629acfd18
Story: 2006896
Task: 37530
2019-11-18 10:28:23 +01:00
kangyufei
be0a9861d0 Switch to Ussuri jobs
Change-Id: I40dbc3c66164725bc4a8af4d0bf9ab481a7d72e7
2019-10-22 13:45:58 +08:00
Quentin Anglade
e599ac9f84 Add support for v2/rating/modules endpoints
This adds support for the new v2 API rating modules endpoints. Unit tests included.

Change-Id: Ie116c518f30128b49c3991f36101db7535af7db1
Story: 2006572
Task: 36680
2019-09-30 16:36:16 +02:00
55b056bc8a Update master for stable/train
Add file to the reno documentation build to show release notes for
stable/train.

Use pbr instruction to increment the minor version number
automatically so that master versions are higher than the versions on
stable/train.

Change-Id: Ia9a85597ccd963eb69f5e04eb1d28d9346f4c31d
Sem-Ver: feature
2019-09-20 16:44:57 +00:00
manchandavishal
296fd22640 Generate PDF documentation
This commit adds a new tox target to build PDF documentation.
It's a part of community goal, see storyboard for more
information.

Change-Id: I6e4f6372ff026a9eb379ee06c683451f58a99976
Story: 2006075
Task: 34812
2019-09-16 16:46:06 +00:00
Justin Ferrieu
c8d7a9e1c5 Add support for POST /v2/dataframes API endpoint to the client
Support for the ``/v2/dataframes`` endpoint has been added to the client.
A new ``dataframes add`` CLI command is also available.

Change-Id: I7fe9072d7280f251edc865a653a0b9ed2ab26c90
Story: 2005890
Task: 35970
2019-08-27 11:50:32 +00:00
Luka Peschke
dd4112acea Add functional test jobs for the v2 client
This adds test jobs for the v2 client, in python2 and python3.

Work items:

* Remove the "functional" tox environment and introduce the "functional-v1"
  and "functional-v2" environments.

* Add zuul base jobs for python2 and python 3 testing. Two jobs inherit from
  each of these new jobs: one for the v1 client and one for the v2 client.

* Add "OS_ENDPOINT" to the list of environment variables forwarded to the
  functional test environments in order to ease local testing.

Change-Id: I54a43a1e844e92730afbf87316b9efe73a08d850
2019-08-27 10:13:32 +02:00
pengyuesheng
3010383f10 Add lower-constraints job
create a tox environment for running the unit tests against the lower
bounds of the dependencies.

Add openstack-tox-lower-constraints job to the zuul configuration.

See http://lists.openstack.org/pipermail/openstack-dev/2018-March/128352.html
for more details.

Change-Id: Iae676c4bbd00836cc6dce0f083f7aa308bbfc372
2019-08-20 13:07:13 +00:00
20 changed files with 258 additions and 62 deletions

View File

@@ -2,4 +2,3 @@
host=review.opendev.org
port=29418
project=openstack/python-cloudkittyclient.git
defaultbranch=stable/train

View File

@@ -21,6 +21,8 @@
cloudkitty: https://opendev.org/openstack/cloudkitty
devstack_localrc:
CLOUDKITTY_FETCHER: keystone
DEVSTACK_GATE_USE_PYTHON3: "True"
USE_PYTHON3: True
devstack_services:
ck-api: true
horizon: false
@@ -39,35 +41,12 @@
vars:
tox_envlist: functional-v2
- job:
name: cloudkittyclient-devstack-functional-base-py3
parent: cloudkittyclient-devstack-functional-base
description: |
Job for cloudkittyclient functional tests, ran in python3.
vars:
devstack_localrc:
DEVSTACK_GATE_USE_PYTHON3: "True"
USE_PYTHON3: "True"
- job:
name: cloudkittyclient-devstack-functional-v1-client-py3
parent: cloudkittyclient-devstack-functional-base-py3
vars:
tox_envlist: functional-v1
- job:
name: cloudkittyclient-devstack-functional-v2-client-py3
parent: cloudkittyclient-devstack-functional-base-py3
vars:
tox_envlist: functional-v2
- project:
templates:
- openstack-lower-constraints-jobs
- check-requirements
- openstack-cover-jobs
- openstack-python-jobs
- openstack-python3-train-jobs
- openstack-python3-ussuri-jobs
- openstackclient-plugin-jobs
- publish-openstack-docs-pti
check:
@@ -76,17 +55,9 @@
voting: true
- cloudkittyclient-devstack-functional-v2-client:
voting: true
- cloudkittyclient-devstack-functional-v1-client-py3:
voting: true
- cloudkittyclient-devstack-functional-v2-client-py3:
voting: true
gate:
jobs:
- cloudkittyclient-devstack-functional-v1-client:
voting: true
- cloudkittyclient-devstack-functional-v2-client:
voting: true
- cloudkittyclient-devstack-functional-v1-client-py3:
voting: true
- cloudkittyclient-devstack-functional-v2-client-py3:
voting: true

View File

@@ -15,9 +15,23 @@
#
from string import Formatter as StringFormatter
from six import add_metaclass
from six.moves.urllib.parse import urlencode
from cloudkittyclient import utils
class HttpDecoratorMeta(type):
ignore = ('get_url', )
def __new__(cls, *args, **kwargs):
return utils.format_http_errors(HttpDecoratorMeta.ignore)(
super(HttpDecoratorMeta, cls).__new__(cls, *args, **kwargs)
)
@add_metaclass(HttpDecoratorMeta)
class BaseManager(object):
"""Base class for Endpoint Manager objects."""

View File

@@ -94,7 +94,7 @@ class CloudKittyShell(cliff.app.App):
super(CloudKittyShell, self).__init__(
description='CloudKitty CLI client',
version=utils.get_version(),
command_manager=CommandManager('cloudkittyclient.v{}'.format(
command_manager=CommandManager('cloudkittyclient_v{}'.format(
self._get_api_version(args[:]),
)),
deferred_help=True,

View File

@@ -139,7 +139,7 @@ class CkDataframesTest(base.BaseFunctionalTest):
def test_dataframes_add_with_no_args(self):
self.assertRaisesRegexp(
RuntimeError,
'error: too few arguments',
'error: the following arguments are required: datafile',
self.runner,
'dataframes add',
fmt='',

View File

@@ -12,8 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from cloudkittyclient.tests import utils
from cloudkittyclient.v2 import dataframes
from cloudkittyclient.v2.rating import modules
from cloudkittyclient.v2 import scope
from cloudkittyclient.v2 import summary
@@ -26,3 +28,4 @@ class BaseAPIEndpointTestCase(utils.BaseTestCase):
self.dataframes = dataframes.DataframesManager(self.api_client)
self.scope = scope.ScopeManager(self.api_client)
self.summary = summary.SummaryManager(self.api_client)
self.rating = modules.RatingManager(self.api_client)

View File

@@ -0,0 +1,38 @@
# Copyright 2019 Objectif Libre
#
# 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.
#
from cloudkittyclient.tests.unit.v2 import base
class TestRating(base.BaseAPIEndpointTestCase):
def test_get_modules(self):
self.rating.get_module()
self.api_client.get.assert_called_once_with('/v2/rating/modules')
def test_get_one_module(self):
self.rating.get_module(module_id="moduleidtest")
self.api_client.get.assert_called_once_with(
'/v2/rating/modules/moduleidtest')
def test_update_one_module(self):
self.rating.update_module(module_id="moduleidtest",
enabled=False, priority=42)
self.api_client.put.assert_called_once_with(
'/v2/rating/modules/moduleidtest',
json={
'enabled': False,
'priority': 42,
})

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Objectif Libre
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -13,8 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
#
import inspect
import sys
import pbr.version
from keystoneauth1.exceptions import http
from oslo_utils import timeutils
@@ -56,3 +59,44 @@ def list_to_cols(list_obj, cols):
for item in list_obj:
values.append(dict_to_cols(item, cols))
return values
def http_error_formatter(func):
"""This decorator catches Http Errors and re-formats them"""
def wrap(*args, **kwargs):
try:
return func(*args, **kwargs)
except http.HttpError as e:
raise http.HttpError(message=e.response.text,
http_status=e.http_status)
return wrap
def format_http_errors(ignore):
"""Applies ``http_error_formatter`` to all methods of a class.
:param ignore: List of function names to ignore
:type ignore: iterable
"""
def wrap(cls):
# If you want pretty errors, use python3.
# __qualname__ does not exist in python 2
if sys.version_info.major < 3:
return cls
def predicate(item):
# This avoids decorating functions of parent classes
return (inspect.isfunction(item)
and item.__name__ not in ignore
and not item.__name__.startswith('_')
and cls.__name__ in item.__qualname__)
for name, func in inspect.getmembers(cls, predicate):
setattr(cls, name, http_error_formatter(func))
return cls
return wrap

View File

@@ -15,6 +15,7 @@
#
from cloudkittyclient.v1 import client
from cloudkittyclient.v2 import dataframes
from cloudkittyclient.v2.rating import modules
from cloudkittyclient.v2 import scope
from cloudkittyclient.v2 import summary
@@ -40,3 +41,4 @@ class Client(client.Client):
self.dataframes = dataframes.DataframesManager(self.api_client)
self.scope = scope.ScopeManager(self.api_client)
self.summary = summary.SummaryManager(self.api_client)
self.rating = modules.RatingManager(self.api_client)

View File

View File

@@ -0,0 +1,59 @@
# Copyright 2019 Objectif Libre
#
# 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.
#
from cloudkittyclient import exc
from cloudkittyclient.v1.client import rating
class RatingManager(rating.RatingManager):
"""Class used to handle /v2/rating/modules endpoint"""
url = '/v2/rating/modules'
def get_module(self, **kwargs):
"""Returns the given module.
If module_id is not specified, returns the list of loaded modules.
:param module_id: ID of the module on which you want information.
:type module_id: str
"""
module_id = kwargs.get('module_id', None)
if module_id is not None:
url = "{}/{}".format(self.url, module_id)
else:
url = self.url
return self.api_client.get(url).json()
def update_module(self, **kwargs):
"""Update the given module.
:param module_id: Id of the module to update.
:type module_id: str
:param enabled: Set to True to enable the module, False to disable it.
:type enabled: bool
:param priority: New priority of the module.
:type priority: int
"""
if not kwargs.get('module_id', None):
raise exc.ArgumentRequired("'module_id' argument is required.")
mutable_fields = ['enabled', 'priority']
changes = {}
for key, value in kwargs.items():
if value is not None and key in mutable_fields:
changes[key] = value
self.api_client.put("{}/{}".format(self.url, kwargs['module_id']),
json=changes)
return self.get_module(**kwargs)

View File

@@ -0,0 +1,29 @@
# Copyright 2019 Objectif Libre
#
# 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.
#
from cliff import lister
from cloudkittyclient import utils
class CliModuleList(lister.Lister):
"""Get loaded rating modules list"""
def get_parser(self, prog_name):
parser = super(CliModuleList, self).get_parser(prog_name)
return parser
def take_action(self, parsed_args):
resp = utils.get_client_from_osc(self).ratingmodules.get_modules_list()
return resp['modules']

View File

@@ -3,6 +3,7 @@
# process, which may cause wedges in the gate later.
openstackdocstheme>=1.30.0 # Apache-2.0
sphinx>=1.6.2,!=1.6.6,!=1.6.7,<2.0.0;python_version=='2.7' # BSD
sphinx>=1.6.2,!=1.6.6,!=1.6.7,!=2.1.0;python_version>='3.4' # BSD
sphinx>=1.8.0,!=2.1.0 # BSD
sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
reno>=2.5.0 # Apache-2.0
cliff>=2.11.0 # Apache-2.0

View File

@@ -5,18 +5,17 @@ CLI Reference
V1 Client
=========
.. autoprogram-cliff:: cloudkittyclient.v1
.. autoprogram-cliff:: cloudkittyclient_v1
:application: cloudkitty
V2 Client
=========
.. autoprogram-cliff:: cloudkittyclient.v2
.. autoprogram-cliff:: cloudkittyclient_v2
:command: dataframes add
.. autoprogram-cliff:: cloudkittyclient.v2
.. autoprogram-cliff:: cloudkittyclient_v2
:command: scope state get
.. autoprogram-cliff:: cloudkittyclient.v2
.. autoprogram-cliff:: cloudkittyclient_v2
:command: summary get

View File

@@ -23,8 +23,11 @@ extensions = [
'cliff.sphinxext',
'sphinx.ext.autodoc',
'openstackdocstheme',
'sphinxcontrib.rsvgconverter',
]
autoprogram_cliff_application = 'cloudkitty'
autoprogram_cliff_ignored = [
"--format", "--column", "--max-width", "--fit-width", "--print-empty",
"--format-config-file", "--noindent", "--quote", "--sort-column",
@@ -74,14 +77,30 @@ html_last_updated_fmt = '%Y-%m-%d %H:%M'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# -- Options for LaTeX output ---------------------------------------------
# Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664
latex_use_xindy = False
latex_domain_indices = False
latex_elements = {
'makeindex': '',
'printindex': '',
'preamble': r'\setcounter{tocdepth}{3}',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
# NOTE: Specify toctree_only=True for a better document structure of
# the generated PDF file.
latex_documents = [
('index',
'%s.tex' % project,
'doc-%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
u'OpenStack Foundation', 'howto', True),
]
# Example configuration for intersphinx: refer to the Python standard library.

View File

@@ -0,0 +1,7 @@
---
upgrade:
- |
Python 2.7 support has been dropped. The last release of
``cloudkittyclient`` to support python 2.7 is OpenStack Train (3.1.0).
The minimum version of Python now supported by ``cloudkittyclient``
is Python 3.6.

View File

@@ -8,6 +8,7 @@ Contents
:maxdepth: 2
unreleased
train
stein
rocky
queens

View File

@@ -0,0 +1,6 @@
==========================
Train Series Release Notes
==========================
.. release-notes::
:branch: stable/train

View File

@@ -6,6 +6,7 @@ description-file =
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/python-cloudkittyclient/latest/
python-requires = >=3.6
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -13,8 +14,6 @@ classifier =
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
@@ -145,7 +144,7 @@ openstack.rating.v2 =
rating_pyscript_update = cloudkittyclient.v1.rating.pyscripts_cli:CliUpdateScript
rating_pyscript_delete = cloudkittyclient.v1.rating.pyscripts_cli:CliDeleteScript
cloudkittyclient.v1 =
cloudkittyclient_v1 =
total_get = cloudkittyclient.v1.report_cli:CliTotalGet
summary_get = cloudkittyclient.v1.report_cli:CliSummaryGet
report_tenant_list = cloudkittyclient.v1.report_cli:CliTenantList
@@ -201,7 +200,7 @@ cloudkittyclient.v1 =
pyscript_update = cloudkittyclient.v1.rating.pyscripts_cli:CliUpdateScript
pyscript_delete = cloudkittyclient.v1.rating.pyscripts_cli:CliDeleteScript
cloudkittyclient.v2 =
cloudkittyclient_v2 =
dataframes_add = cloudkittyclient.v2.dataframes_cli:CliDataframesAdd
scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet

31
tox.ini
View File

@@ -1,11 +1,13 @@
[tox]
minversion = 2.0
envlist = py27,py36,py37,pypy,pep8
minversion = 3.1.1
envlist = py36,py37,pep8
skipsdist = True
ignore_basepython_conflict = True
[testenv]
basepython = python3
usedevelop = True
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/train} -U {opts} {packages}
install_command = pip install -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt
@@ -13,7 +15,6 @@ deps = -r{toxinidir}/requirements.txt
commands = stestr run {posargs}
[testenv:cover]
basepython = python3
setenv =
VIRTUAL_ENV={envdir}
PYTHON=coverage run --source cloudkittyclient --parallel-mode
@@ -25,7 +26,6 @@ commands =
coverage report
[testenv:debug]
basepython = python3
commands = oslo_debug_helper -t cloudkittyclient/tests {posargs}
[testenv:functional-v1]
@@ -39,17 +39,23 @@ setenv = OS_RATING_API_VERSION=2
commands = stestr run --concurrency=1 --test-path ./cloudkittyclient/tests/functional/v2
[testenv:pep8]
basepython = python3
commands = flake8
[testenv:venv]
basepython = python3
commands = {posargs}
[testenv:docs]
basepython = python3
deps = -r{toxinidir}/doc/requirements.txt
commands = sphinx-build -W -b html doc/source doc/build/html
commands = sphinx-build --keep-going -b html doc/source doc/build/html
[testenv:pdf-docs]
envdir = {toxworkdir}/docs
deps = {[testenv:docs]deps}
whitelist_externals =
make
commands =
sphinx-build --keep-going -b latex doc/source doc/build/pdf
make -C doc/build/pdf
[flake8]
# E123, E125 skipped as they are invalid PEP-8.
@@ -63,14 +69,13 @@ exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,releasenotes
import_exceptions = cloudkittyclient.i18n
[testenv:releasenotes]
basepython = python3
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/train}
-c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
-r{toxinidir}/doc/requirements.txt
commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
commands =
sphinx-build -a -E -W -d releasenotes/build/doctrees --keep-going -b html releasenotes/source releasenotes/build/html
[testenv:lower-constraints]
basepython = python3
deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt