Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57d4563817 | ||
|
|
b465e86703 | ||
|
|
1724798fd7 | ||
|
|
1ee30ec19c | ||
|
|
8b26d758c0 | ||
| 377172f39d | |||
| 98e177260d | |||
|
|
3b49fbd4d0 | ||
|
|
e9a92a2941 | ||
|
|
1ed287c92a | ||
|
|
63ac84b165 | ||
|
|
1cf5b3aca2 | ||
|
|
503dd3247a | ||
|
|
7b9d447eb8 | ||
|
|
a9eb87c436 | ||
|
|
fff37a84fa | ||
|
|
81cdcba4f3 | ||
|
|
214083c695 | ||
|
|
c78ae05005 | ||
| 1348fd67e1 |
@@ -2,3 +2,4 @@
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/python-cloudkittyclient.git
|
||||
defaultbranch=stable/stein
|
||||
|
||||
24
.zuul.yaml
24
.zuul.yaml
@@ -19,6 +19,8 @@
|
||||
vars:
|
||||
devstack_plugins:
|
||||
cloudkitty: https://git.openstack.org/openstack/cloudkitty
|
||||
devstack_localrc:
|
||||
CLOUDKITTY_FETCHER: keystone
|
||||
devstack_services:
|
||||
ck-api: true
|
||||
horizon: false
|
||||
@@ -26,12 +28,34 @@
|
||||
zuul_work_dir: src/git.openstack.org/openstack/python-cloudkittyclient
|
||||
tox_envlist: functional
|
||||
|
||||
- job:
|
||||
name: cloudkittyclient-devstack-functional-py3
|
||||
parent: cloudkittyclient-devstack-functional
|
||||
description: |
|
||||
Job for cloudkittyclient functional tests, ran in python3.
|
||||
vars:
|
||||
devstack_localrc:
|
||||
DEVSTACK_GATE_USE_PYTHON3: "True"
|
||||
USE_PYTHON3: "True"
|
||||
|
||||
- project:
|
||||
templates:
|
||||
- check-requirements
|
||||
- openstack-cover-jobs
|
||||
- openstack-python-jobs
|
||||
- openstack-python35-jobs
|
||||
- openstack-python36-jobs
|
||||
- openstackclient-plugin-jobs
|
||||
- publish-openstack-docs-pti
|
||||
check:
|
||||
jobs:
|
||||
- cloudkittyclient-devstack-functional:
|
||||
voting: true
|
||||
- cloudkittyclient-devstack-functional-py3:
|
||||
voting: true
|
||||
gate:
|
||||
jobs:
|
||||
- cloudkittyclient-devstack-functional:
|
||||
voting: true
|
||||
- cloudkittyclient-devstack-functional-py3:
|
||||
voting: true
|
||||
|
||||
@@ -30,7 +30,12 @@ def make_client(instance):
|
||||
version,
|
||||
API_VERSIONS)
|
||||
instance.setup_auth()
|
||||
return ck_client(session=instance.session)
|
||||
adapter_options = dict(
|
||||
interface=instance.interface,
|
||||
region_name=instance.region_name,
|
||||
)
|
||||
return ck_client(session=instance.session,
|
||||
adapter_options=adapter_options)
|
||||
|
||||
|
||||
def build_option_parser(parser):
|
||||
|
||||
@@ -22,8 +22,8 @@ class CkReportTest(base.BaseFunctionalTest):
|
||||
self.runner = self.cloudkitty
|
||||
|
||||
def test_get_summary(self):
|
||||
resp = self.runner('summary get')[0]
|
||||
self.assertEqual(resp['Resource Type'], 'ALL')
|
||||
resp = self.runner('summary get')
|
||||
self.assertEqual(len(resp), 0)
|
||||
|
||||
def test_get_summary_with_groupby(self):
|
||||
resp = self.runner('summary get', params='-g res_type tenant_id')
|
||||
|
||||
48
cloudkittyclient/tests/unit/v1/test_rating.py
Normal file
48
cloudkittyclient/tests/unit/v1/test_rating.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# 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.
|
||||
#
|
||||
import decimal
|
||||
|
||||
from cloudkittyclient import exc
|
||||
from cloudkittyclient.tests.unit.v1 import base
|
||||
|
||||
|
||||
class TestRating(base.BaseAPIEndpointTestCase):
|
||||
|
||||
def test_quote_request(self):
|
||||
res_data = [{'usage': {
|
||||
'instance': [{
|
||||
'vol': {'unit': 'undef', 'qty': '1'},
|
||||
'rating': {'price': decimal.Decimal(1)},
|
||||
'desc': {
|
||||
'disk_total_display': 1,
|
||||
'image_id': 'c43a3e7d-c4e6-45d6-8c8d-e2832a45bc0a',
|
||||
'ram': 64,
|
||||
'ephemeral': 0,
|
||||
'vcpus': 1,
|
||||
'source_type': 'image',
|
||||
'disk_total': 1,
|
||||
'flavor_id': '42',
|
||||
'flavor': 'm1.nano',
|
||||
'disk': 1,
|
||||
'source_val': 'c43a3e7d-c4e6-45d6-8c8d-e2832a45bc0a'}
|
||||
}]
|
||||
}}]
|
||||
|
||||
self.rating.get_quotation(res_data=res_data)
|
||||
self.api_client.post.assert_called_once_with(
|
||||
'/v1/rating/quote/', json={'resources': res_data})
|
||||
|
||||
def test_get_quotation_no_res_data(self):
|
||||
self.assertRaises(exc.ArgumentRequired, self.rating.get_quotation)
|
||||
63
cloudkittyclient/tests/unit/v1/test_report_cli.py
Normal file
63
cloudkittyclient/tests/unit/v1/test_report_cli.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# Copyright 2018 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.
|
||||
#
|
||||
import collections
|
||||
import mock
|
||||
|
||||
from cloudkittyclient.tests.unit.v1 import base
|
||||
from cloudkittyclient.v1 import report_cli
|
||||
|
||||
|
||||
class TestReportCli(base.BaseAPIEndpointTestCase):
|
||||
|
||||
def test_report_tenant_list(self):
|
||||
|
||||
class DummyAPIClient(object):
|
||||
def get_tenants(*args, **kwargs):
|
||||
return ['ee530dfc-319a-438f-9d43-346cfef501d6',
|
||||
'91743a9a-688b-4526-b568-7b501531176c',
|
||||
'4468704c-972e-4cfd-a342-9b71c493b79b']
|
||||
|
||||
class ClientWrap(object):
|
||||
report = DummyAPIClient()
|
||||
|
||||
class DummyParsedArgs(object):
|
||||
def __init__(self):
|
||||
self.begin = '2042-01-01T00:00:00'
|
||||
self.end = '2042-12-01T00:00:00'
|
||||
|
||||
class DummyCliTenantList(report_cli.CliTenantList):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __get_client_from_osc(*args):
|
||||
return ClientWrap()
|
||||
|
||||
parsed_args = DummyParsedArgs()
|
||||
cli_class_instance = DummyCliTenantList()
|
||||
|
||||
with mock.patch('cloudkittyclient.utils.get_client_from_osc',
|
||||
new=__get_client_from_osc):
|
||||
# NOTE(peschk_l): self is only used used to get a client so just we
|
||||
# just override __init__ in order to skip class instanciation. In
|
||||
# python3 we could just have passed None
|
||||
result = report_cli.CliTenantList.take_action(
|
||||
cli_class_instance, parsed_args)
|
||||
|
||||
assert len(result) == 2
|
||||
assert result[0] == ('Tenant ID', )
|
||||
assert isinstance(result[1], collections.Iterable)
|
||||
|
||||
for res in result[1]:
|
||||
assert isinstance(res, collections.Iterable)
|
||||
@@ -25,12 +25,26 @@ from cloudkittyclient.v1 import storage
|
||||
|
||||
class Client(object):
|
||||
|
||||
def __init__(self, session=None, adapter_options={}, **kwargs):
|
||||
def __init__(self,
|
||||
session=None,
|
||||
adapter_options={},
|
||||
cacert=None,
|
||||
insecure=False,
|
||||
**kwargs):
|
||||
adapter_options.setdefault('service_type', 'rating')
|
||||
|
||||
if insecure:
|
||||
verify_cert = False
|
||||
else:
|
||||
if cacert:
|
||||
verify_cert = cacert
|
||||
else:
|
||||
verify_cert = True
|
||||
|
||||
self.session = session
|
||||
if self.session is None:
|
||||
self.session = ks_session.Session(**kwargs)
|
||||
self.session = ks_session.Session(
|
||||
verify=verify_cert, **kwargs)
|
||||
|
||||
self.api_client = adapter.Adapter(
|
||||
session=self.session, **adapter_options)
|
||||
|
||||
@@ -78,8 +78,10 @@ class RatingManager(base.BaseManager):
|
||||
"""
|
||||
if not kwargs.get('res_data', None):
|
||||
raise exc.ArgumentRequired("'res_data' argument is required.")
|
||||
url = self.get_url('quote')
|
||||
return self.api_client.post(url, kwargs['res_data'])
|
||||
url = self.get_url('quote', {})
|
||||
|
||||
body = {'resources': kwargs['res_data']}
|
||||
return self.api_client.post(url, json=body).json()
|
||||
|
||||
|
||||
class CliModuleGet(lister.Lister):
|
||||
|
||||
@@ -114,8 +114,11 @@ class CliTenantList(lister.Lister):
|
||||
raise exc.InvalidArgumentError(
|
||||
'Invalid timestamp "{}"'.format(value))
|
||||
client = utils.get_client_from_osc(self)
|
||||
return (('Tenant ID', ),
|
||||
(client.report.get_tenants(**vars(parsed_args)), ))
|
||||
tenants = client.report.get_tenants(**vars(parsed_args))
|
||||
output = []
|
||||
for tenant in tenants:
|
||||
output.append((tenant, ))
|
||||
return (('Tenant ID', ), output)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliTenantList, self).get_parser(prog_name)
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
openstackdocstheme>=1.18.1 # Apache-2.0
|
||||
sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
|
||||
reno>=2.5.0 # Apache2
|
||||
sphinx>=1.6.2,!=1.6.6,!=1.6.7 # BSD
|
||||
reno>=2.5.0 # Apache-2.0
|
||||
|
||||
@@ -49,6 +49,16 @@ Else, use it the same way as any other OpenStack client::
|
||||
u'res_type': u'ALL',
|
||||
u'tenant_id': u'bea6a24f77e946b0a92dca7c78b7870b'}]}
|
||||
|
||||
.. warning::
|
||||
|
||||
If you want to use SSL with the client as a python library, you need to
|
||||
provide a cert to keystone's session object. Else, two additional options
|
||||
are available if you provide an ``auth`` object to the client: ``insecure``
|
||||
and ``cacert``::
|
||||
|
||||
>>> client = ck_client.Client(
|
||||
'1', auth=auth, insecure=False, cacert='/path/to/ca')
|
||||
|
||||
When using the ``cloudkitty`` CLI client with keystone authentication, the
|
||||
auth plugin to use should automagically be detected. If not, you can specify
|
||||
the auth plugin to use with ``--os-auth-type/--os-auth-plugin``::
|
||||
|
||||
23
lower-constraints.txt
Normal file
23
lower-constraints.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# requirements
|
||||
pbr==2.0.0 # Apache-2.0
|
||||
cliff==2.11.0 # Apache-2.0
|
||||
keystoneauth1==3.4.0 # Apache-2.0
|
||||
oslo.utils==3.35 # Apache-2.0
|
||||
oslo.log==3.36 # Apache-2.0
|
||||
PyYAML==3.12 # MIT
|
||||
jsonpath-rw-ext==1.0 # Apache-2.0
|
||||
six==1.11 # MIT
|
||||
os-client-config==1.29.0 # Apache-2.0
|
||||
|
||||
# test-requirements.txt
|
||||
coverage==4.0 # Apache-2.0
|
||||
python-subunit==0.0.18 # Apache-2.0/BSD
|
||||
oslotest==1.10.0 # Apache-2.0
|
||||
stestr==2.0 # Apache-2.0
|
||||
mock==2.0 # BSD
|
||||
python-openstackclient==3.14 # Apache-2.0
|
||||
|
||||
# doc/requirements.txt
|
||||
openstackdocstheme==1.18.1 # Apache-2.0
|
||||
sphinx==1.6.2 # BSD
|
||||
reno==2.5.0 # Apache2
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
The ``rating.get_quotation`` method of the client has been fixed: the json
|
||||
body has been updated to match the API reference.
|
||||
@@ -16,7 +16,6 @@
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
import pbr.version
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
@@ -26,8 +25,8 @@ import pbr.version
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'oslosphinx',
|
||||
'reno.sphinxext',
|
||||
'openstackdocstheme',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@@ -46,16 +45,12 @@ master_doc = 'index'
|
||||
project = u'Cloudkitty Client Release Notes'
|
||||
copyright = u'2016, Cloudkitty 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.
|
||||
#
|
||||
|
||||
cloudkittyclient_version = pbr.version.VersionInfo('python-cloudkittyclient')
|
||||
# Release notes are version independent.
|
||||
# The short X.Y version.
|
||||
version = cloudkittyclient_version.canonical_version_string()
|
||||
version = ''
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = cloudkittyclient_version.version_string_with_vcs()
|
||||
release = ''
|
||||
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -100,7 +95,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = 'openstackdocs'
|
||||
|
||||
# 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
|
||||
|
||||
@@ -8,6 +8,7 @@ Contents
|
||||
:maxdepth: 2
|
||||
|
||||
unreleased
|
||||
rocky
|
||||
queens
|
||||
|
||||
Indices and tables
|
||||
|
||||
6
releasenotes/source/rocky.rst
Normal file
6
releasenotes/source/rocky.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
===================================
|
||||
Rocky Series Release Notes
|
||||
===================================
|
||||
|
||||
.. release-notes::
|
||||
:branch: stable/rocky
|
||||
@@ -2,12 +2,12 @@
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
cliff>=2.11.0,<3.0 # Apache-2.0
|
||||
keystoneauth1>=3.4.0,<4.0 # Apache-2.0
|
||||
oslo.utils>=3.35,<4.0 # Apache-2.0
|
||||
oslo.log>=3.36,<4.0 # Apache-2.0
|
||||
PyYAML>=3.12,<4.0 # MIT
|
||||
pbr>=2.0.0,!=2.1.0 # Apache-2.0
|
||||
cliff>=2.11.0 # Apache-2.0
|
||||
keystoneauth1>=3.4.0 # Apache-2.0
|
||||
oslo.utils>=3.35 # Apache-2.0
|
||||
oslo.log>=3.36 # Apache-2.0
|
||||
PyYAML>=3.12 # MIT
|
||||
jsonpath-rw-ext>=1.0 # Apache-2.0
|
||||
six>=1.11,<2.0 # MIT
|
||||
six>=1.11 # MIT
|
||||
os-client-config>=1.29.0 # Apache-2.0
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
|
||||
|
||||
coverage!=4.4,>=4.0 # Apache-2.0
|
||||
coverage>=4.0,!=4.4 # Apache-2.0
|
||||
python-subunit>=0.0.18 # Apache-2.0/BSD
|
||||
oslotest>=1.10.0 # Apache-2.0
|
||||
stestr>=2.0 # Apache-2.0
|
||||
|
||||
16
tox.ini
16
tox.ini
@@ -1,17 +1,29 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
minversion = 2.0
|
||||
envlist = py35,py27,pypy,pep8
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -U {opts} {packages}
|
||||
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/stein} -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = stestr run {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
basepython = python3
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
PYTHON=coverage run --source cloudkittyclient --parallel-mode
|
||||
commands =
|
||||
stestr run {posargs}
|
||||
coverage combine
|
||||
coverage html -d cover
|
||||
coverage xml -o cover/coverage.xml
|
||||
coverage report
|
||||
|
||||
[testenv:debug]
|
||||
basepython = python3
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
Reference in New Issue
Block a user