Compare commits

..

8 Commits
4.0.0 ... 3.1.0

Author SHA1 Message Date
Zuul
c5d1526dec Merge "Add support for POST /v2/dataframes API endpoint to the client" into stable/train 2019-09-23 07:52:15 +00:00
Zuul
729ab402a5 Merge "Add functional test jobs for the v2 client" into stable/train 2019-09-23 07:51:04 +00:00
Zuul
3bcb6949b7 Merge "Add lower-constraints job" into stable/train 2019-09-23 07:51:03 +00:00
Justin Ferrieu
71fa216168 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
(cherry picked from commit c8d7a9e1c5)
2019-09-20 14:34:45 -05:00
Luka Peschke
41fecfcd1e 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
(cherry picked from commit dd4112acea)
2019-09-20 14:34:38 -05:00
pengyuesheng
5c31e34202 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
(cherry picked from commit 3010383f10)
2019-09-20 14:34:30 -05:00
22e9ffdb8b Update TOX/UPPER_CONSTRAINTS_FILE for stable/train
Update the URL to the upper-constraints file to point to the redirect
rule on releases.openstack.org so that anyone working on this branch
will switch to the correct upper-constraints list automatically when
the requirements repository branches.

Until the requirements repository has as stable/train branch, tests will
continue to use the upper-constraints list on master.

Change-Id: I2bc755e71ad06ebbb4aef23b25aa1cf310d0b897
2019-09-20 16:44:53 +00:00
e251e5c451 Update .gitreview for stable/train
Change-Id: Ia90ce3ac73c87953fc379d43c8005e24e57c5db5
2019-09-20 16:44:48 +00:00
20 changed files with 62 additions and 258 deletions

View File

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

View File

@@ -21,8 +21,6 @@
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
@@ -41,12 +39,35 @@
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-python3-ussuri-jobs
- openstack-python-jobs
- openstack-python3-train-jobs
- openstackclient-plugin-jobs
- publish-openstack-docs-pti
check:
@@ -55,9 +76,17 @@
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,23 +15,9 @@
#
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: the following arguments are required: datafile',
'error: too few arguments',
self.runner,
'dataframes add',
fmt='',

View File

@@ -12,10 +12,8 @@
# 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
@@ -28,4 +26,3 @@ 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

@@ -1,38 +0,0 @@
# 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,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Objectif Libre
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -12,12 +13,8 @@
# 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
@@ -59,44 +56,3 @@ 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,7 +15,6 @@
#
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
@@ -41,4 +40,3 @@ 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

@@ -1,59 +0,0 @@
# 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

@@ -1,29 +0,0 @@
# 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,7 +3,6 @@
# process, which may cause wedges in the gate later.
openstackdocstheme>=1.30.0 # Apache-2.0
sphinx>=1.8.0,!=2.1.0 # BSD
sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
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
reno>=2.5.0 # Apache-2.0
cliff>=2.11.0 # Apache-2.0

View File

@@ -5,17 +5,18 @@ 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,11 +23,8 @@ 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",
@@ -77,30 +74,14 @@ 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',
'doc-%s.tex' % project,
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'howto', True),
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.

View File

@@ -1,7 +0,0 @@
---
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,7 +8,6 @@ Contents
:maxdepth: 2
unreleased
train
stein
rocky
queens

View File

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

View File

@@ -6,7 +6,6 @@ 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
@@ -14,6 +13,8 @@ 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
@@ -144,7 +145,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
@@ -200,7 +201,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,13 +1,11 @@
[tox]
minversion = 3.1.1
envlist = py36,py37,pep8
minversion = 2.0
envlist = py27,py36,py37,pypy,pep8
skipsdist = True
ignore_basepython_conflict = True
[testenv]
basepython = python3
usedevelop = True
install_command = pip install -U {opts} {packages}
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/train} -U {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt
@@ -15,6 +13,7 @@ deps = -r{toxinidir}/requirements.txt
commands = stestr run {posargs}
[testenv:cover]
basepython = python3
setenv =
VIRTUAL_ENV={envdir}
PYTHON=coverage run --source cloudkittyclient --parallel-mode
@@ -26,6 +25,7 @@ commands =
coverage report
[testenv:debug]
basepython = python3
commands = oslo_debug_helper -t cloudkittyclient/tests {posargs}
[testenv:functional-v1]
@@ -39,23 +39,17 @@ 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 --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
commands = sphinx-build -W -b html doc/source doc/build/html
[flake8]
# E123, E125 skipped as they are invalid PEP-8.
@@ -69,13 +63,14 @@ 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://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/train}
-r{toxinidir}/doc/requirements.txt
commands =
sphinx-build -a -E -W -d releasenotes/build/doctrees --keep-going -b html releasenotes/source releasenotes/build/html
commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
[testenv:lower-constraints]
basepython = python3
deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt