Compare commits

..

3 Commits

Author SHA1 Message Date
Matt Crees
c151d6bba8 Fix reprocessing POST request
The POST request for triggering reprocessing needs to be made to
``/v2/task/reprocesses``. This is the same as for other requests, so we
can drop ``url_for_post``.

Change-Id: If630d4f313c875733dbe1937ff7ca625821e04af
(cherry picked from commit 6ee36ef0e3)
2024-04-29 16:48:30 +00:00
61d7fcef7b Update TOX_CONSTRAINTS_FILE for stable/2023.2
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/2023.2 branch, tests will
continue to use the upper-constraints list on master.

Change-Id: Ie293da0dd38d6dd04e7d37d5470b88822a9a78d7
2023-09-07 09:35:32 +00:00
f34ec5a89d Update .gitreview for stable/2023.2
Change-Id: I1cc1416b2dcd9cb28d3e1e75a427b4baf635cd02
2023-09-07 09:35:31 +00:00
36 changed files with 82 additions and 276 deletions

View File

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

View File

@@ -7,7 +7,6 @@
run: playbooks/cloudkittyclient-devstack-functional/run.yaml
post-run: playbooks/cloudkittyclient-devstack-functional/post.yaml
required-projects:
- name: openstack/ceilometer
- name: openstack/cloudkitty
- name: openstack/python-cloudkittyclient
roles:
@@ -19,10 +18,11 @@
- ^releasenotes/.*$
vars:
devstack_plugins:
ceilometer: https://opendev.org/openstack/ceilometer
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

View File

@@ -14,7 +14,7 @@
from osc_lib import utils
DEFAULT_API_VERSION = '2'
DEFAULT_API_VERSION = '1'
API_VERSION_OPTION = 'os_rating_api_version'
API_NAME = "rating"
API_VERSIONS = {

View File

@@ -18,7 +18,7 @@ from sys import argv
import cliff.app
from cliff.commandmanager import CommandManager
from openstack import config as occ
import os_client_config
from oslo_log import log
from cloudkittyclient import client
@@ -90,7 +90,7 @@ class CloudKittyShell(cliff.app.App):
def __init__(self, args):
self._args = args
self.cloud_config = occ.OpenStackConfig()
self.cloud_config = os_client_config.OpenStackConfig()
super(CloudKittyShell, self).__init__(
description='CloudKitty CLI client',
version=utils.get_version(),
@@ -128,7 +128,7 @@ class CloudKittyShell(cliff.app.App):
@property
def client(self):
if self._client is None:
self.cloud = self.cloud_config.get_one(
self.cloud = self.cloud_config.get_one_cloud(
argparse=self.options)
session = self.cloud.get_session()
adapter_options = dict(

View File

@@ -13,9 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from datetime import datetime
from datetime import timedelta
from cloudkittyclient.tests.functional import base
@@ -139,15 +136,13 @@ class CkHashmapTest(base.BaseFunctionalTest):
self.assertEqual(len(resp), 0)
def test_create_get_update_delete_mapping_service(self):
future_date = datetime.now() + timedelta(days=1)
date_iso = future_date.isoformat()
resp = self.runner('hashmap service create', params='testservice')[0]
service_id = resp['Service ID']
self._services.append(service_id)
# Create mapping
resp = self.runner('hashmap mapping create',
params=f'-s {service_id} 12 --start {date_iso}')[0]
params='-s {} 12'.format(service_id))[0]
mapping_id = resp['Mapping ID']
self._mappings.append(mapping_id)
self.assertEqual(resp['Service ID'], service_id)
@@ -178,8 +173,6 @@ class CkHashmapTest(base.BaseFunctionalTest):
'hashmap service delete', params=service_id, has_output=False)
def test_create_get_update_delete_mapping_field(self):
future_date = datetime.now() + timedelta(days=1)
date_iso = future_date.isoformat()
resp = self.runner('hashmap service create', params='testservice')[0]
service_id = resp['Service ID']
self._services.append(service_id)
@@ -192,8 +185,7 @@ class CkHashmapTest(base.BaseFunctionalTest):
# Create mapping
resp = self.runner(
'hashmap mapping create',
params=f'--field-id {field_id} 12 --value '
f'testvalue --start {date_iso}')[0]
params='--field-id {} 12 --value testvalue'.format(field_id))[0]
mapping_id = resp['Mapping ID']
self._mappings.append(service_id)
self.assertEqual(resp['Field ID'], field_id)
@@ -211,45 +203,6 @@ class CkHashmapTest(base.BaseFunctionalTest):
params='--cost 10 {}'.format(mapping_id))[0]
self.assertEqual(float(resp['Cost']), float(10))
def test_create_get_update_delete_mapping_field_started(self):
resp = self.runner('hashmap service create',
params='testservice_date_started')[0]
service_id = resp['Service ID']
self._services.append(service_id)
resp = self.runner(
'hashmap field create',
params='{} testfield_date_started'.format(service_id))[0]
field_id = resp['Field ID']
self._fields.append(field_id)
# Create mapping
resp = self.runner(
'hashmap mapping create',
params=f'--field-id {field_id} 12 --value '
f'testvalue')[0]
mapping_id = resp['Mapping ID']
self._mappings.append(service_id)
self.assertEqual(resp['Field ID'], field_id)
self.assertEqual(float(resp['Cost']), float(12))
self.assertEqual(resp['Value'], 'testvalue')
# Get mapping
resp = self.runner(
'hashmap mapping get', params=mapping_id)[0]
self.assertEqual(resp['Mapping ID'], mapping_id)
self.assertEqual(float(resp['Cost']), float(12))
# Should not be able to update a rule that is running (start < now)
try:
self.runner('hashmap mapping update',
params='--cost 10 {}'.format(mapping_id))[0]
except RuntimeError as e:
expected_error = ("You are allowed to update only the attribute "
"[end] as this rule is already running as it "
"started on ")
self.assertIn(expected_error, str(e))
def test_group_mappings_get(self):
# Service and group
resp = self.runner('hashmap service create', params='testservice')[0]

View File

@@ -13,9 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from datetime import datetime
from datetime import timedelta
from cloudkittyclient.tests.functional import base
@@ -26,12 +23,9 @@ class CkPyscriptTest(base.BaseFunctionalTest):
self.runner = self.cloudkitty
def test_create_get_update_list_delete(self):
future_date = datetime.now() + timedelta(days=1)
date_iso = future_date.isoformat()
# Create
resp = self.runner(
'pyscript create', params=f"testscript "
f"'return 0' --start {date_iso}")[0]
'pyscript create', params="testscript 'return 0'")[0]
script_id = resp['Script ID']
self.assertEqual(resp['Name'], 'testscript')
@@ -43,9 +37,8 @@ class CkPyscriptTest(base.BaseFunctionalTest):
# Update
resp = self.runner(
'pyscript update',
params="-d 'return 1' {} --description "
"desc".format(script_id))[0]
self.assertEqual(resp['Script Description'], 'desc')
params="-n newname -d 'return 1' {}".format(script_id))[0]
self.assertEqual(resp['Name'], 'newname')
self.assertEqual(resp['Script ID'], script_id)
self.assertEqual(resp['Data'], 'return 1')
@@ -53,49 +46,13 @@ class CkPyscriptTest(base.BaseFunctionalTest):
resp = self.runner('pyscript list')
self.assertEqual(len(resp), 1)
resp = resp[0]
self.assertEqual(resp['Script Description'], 'desc')
self.assertEqual(resp['Name'], 'newname')
self.assertEqual(resp['Script ID'], script_id)
self.assertEqual(resp['Data'], 'return 1')
# Delete
self.runner('pyscript delete', params=script_id, has_output=False)
def test_create_get_update_list_delete_started(self):
# Create
resp = self.runner(
'pyscript create', params="testscript_started "
"'return 0'")[0]
script_id = resp['Script ID']
self.assertEqual(resp['Name'], 'testscript_started')
# Get
resp = self.runner('pyscript get', params=script_id)[0]
self.assertEqual(resp['Name'], 'testscript_started')
self.assertEqual(resp['Script ID'], script_id)
# Should not be able to update a rule that is running (start < now)
try:
self.runner(
'pyscript update',
params="-d 'return 1' {} --description "
"desc".format(script_id))[0]
except RuntimeError as e:
expected_error = ("You are allowed to update only the attribute "
"[end] as this rule is already running as it "
"started on ")
self.assertIn(expected_error, str(e))
# List
resp = self.runner('pyscript list')
self.assertEqual(len(resp), 1)
resp = resp[0]
self.assertEqual(resp['Script Description'], None)
self.assertEqual(resp['Script ID'], script_id)
self.assertEqual(resp['Data'], 'return 0')
# Delete
self.runner('pyscript delete', params=script_id, has_output=False)
class OSCPyscriptTest(CkPyscriptTest):

View File

@@ -110,10 +110,7 @@ class TestHashmap(base.BaseAPIEndpointTestCase):
self.assertRaises(exc.ArgumentRequired, self.hashmap.get_mapping)
def test_create_mapping(self):
kwargs = dict(cost=2, value='value', field_id='field_id',
name='name', start="2024-01-01",
end="2024-01-01",
description="description")
kwargs = dict(cost=2, value='value', field_id='field_id')
body = dict(
cost=kwargs.get('cost'),
value=kwargs.get('value'),
@@ -122,10 +119,6 @@ class TestHashmap(base.BaseAPIEndpointTestCase):
group_id=kwargs.get('group_id'),
tenant_id=kwargs.get('tenant_id'),
type=kwargs.get('type') or 'flat',
start="2024-01-01",
end="2024-01-01",
description="description",
name='name'
)
self.hashmap.create_mapping(**kwargs)
self.api_client.post.assert_called_once_with(

View File

@@ -38,8 +38,7 @@ class TestPyscripts(base.BaseAPIEndpointTestCase):
self.assertRaises(exc.ArgumentRequired, self.pyscripts.get_script)
def test_create_script(self):
kwargs = dict(name='name', data='data', start=None,
end=None, description=None)
kwargs = dict(name='name', data='data')
self.pyscripts.create_script(**kwargs)
self.api_client.post.assert_called_once_with(
'/v1/rating/module_config/pyscripts/scripts/', json=kwargs)

View File

@@ -13,6 +13,7 @@
# under the License.
#
import inspect
import sys
import pbr.version
@@ -81,6 +82,11 @@ def format_http_errors(ignore):
"""
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)

View File

@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
#
import uuid
from cloudkittyclient.common import base
from cloudkittyclient import exc
@@ -173,14 +171,6 @@ class HashmapManager(base.BaseManager):
:type type: str
:param value: Value of the mapping
:type value: str
:param name: Name of the mapping
:type name: str
:param start: Date the mapping starts being valid
:type start: str
:param end: Date the mapping stops being valid
:type end: str
:param description: Description of the mapping
:type description: str
"""
if kwargs.get('cost') is None:
raise exc.ArgumentRequired("'cost' argument is required")
@@ -206,16 +196,6 @@ class HashmapManager(base.BaseManager):
tenant_id=kwargs.get('tenant_id'),
type=kwargs.get('type') or 'flat',
)
if kwargs.get('description'):
body['description'] = kwargs.get('description')
if kwargs.get('start'):
body['start'] = kwargs.get('start')
if kwargs.get('end'):
body['end'] = kwargs.get('end')
if kwargs.get('name'):
body['name'] = kwargs.get('name')
else:
body['name'] = uuid.uuid4().hex[:24]
url = self.get_url('mappings', kwargs)
return self.api_client.post(url, json=body).json()

View File

@@ -257,10 +257,6 @@ class CliCreateMapping(lister.Lister):
('service_id', 'Service ID'),
('group_id', 'Group ID'),
('tenant_id', 'Project ID'),
('name', 'Mapping Name'),
('start', 'Mapping Start Date'),
('end', 'Mapping End Date'),
('Description', 'Mapping Description')
]
def take_action(self, parsed_args):
@@ -279,11 +275,6 @@ class CliCreateMapping(lister.Lister):
parser.add_argument('-t', '--type', type=str, help='Mapping type')
parser.add_argument('--value', type=str, help='Value')
parser.add_argument('cost', type=float, help='Cost')
parser.add_argument('--name', type=str, help='Mapping Name')
parser.add_argument('--start', type=str, help='Mapping Start')
parser.add_argument('--end', type=str, help='Mapping End')
parser.add_argument('--description', type=str,
help='Mapping Description')
return parser
@@ -330,11 +321,6 @@ class CliUpdateMapping(lister.Lister):
parser.add_argument('--value', type=str, help='Value')
parser.add_argument('--cost', type=str, help='Cost')
parser.add_argument('mapping_id', type=str, help='Mapping ID')
parser.add_argument('--name', type=str, help='Mapping Name')
parser.add_argument('--start', type=str, help='Mapping Start')
parser.add_argument('--end', type=str, help='Mapping End')
parser.add_argument('--description', type=str,
help='Mapping Description')
return parser

View File

@@ -50,22 +50,13 @@ class PyscriptManager(base.BaseManager):
:type name: str
:param data: Content of the script
:type data: str
:param start: Date the script starts being valid
:type start: str
:param end: Date the script stops being valid
:type end: str
:param description: Description of the script
:type description: str
"""
for arg in ('name', 'data'):
if not kwargs.get(arg):
raise exc.ArgumentRequired(
"'Argument {} is required.'".format(arg))
url = self.get_url('scripts', kwargs)
body = dict(name=kwargs['name'], data=kwargs['data'],
start=kwargs.get('start'),
end=kwargs.get('end'),
description=kwargs.get('description'))
body = dict(name=kwargs['name'], data=kwargs['data'])
return self.api_client.post(url, json=body).json()
def update_script(self, **kwargs):
@@ -77,17 +68,11 @@ class PyscriptManager(base.BaseManager):
:type name: str
:param data: Content of the script
:type data: str
:param start: Date the script starts being valid
:type start: str
:param end: Date the script stops being valid
:type end: str
:param description: Description of the script
:type description: str
"""
if not kwargs.get('script_id'):
raise exc.ArgumentRequired("Argument 'script_id' is required.")
script = self.get_script(script_id=kwargs['script_id'])
for key in ('name', 'data', 'start', 'end', 'description'):
for key in ('name', 'data'):
if kwargs.get(key):
script[key] = kwargs[key]
script.pop('checksum', None)

View File

@@ -26,9 +26,6 @@ class BaseScriptCli(lister.Lister):
('script_id', 'Script ID'),
('checksum', 'Checksum'),
('data', 'Data'),
('start', 'Script Start Date'),
('end', 'Script End Date'),
('description', 'Script Description')
]
@@ -85,10 +82,6 @@ class CliCreateScript(BaseScriptCli):
parser = super(CliCreateScript, self).get_parser(prog_name)
parser.add_argument('name', type=str, help='Script Name')
parser.add_argument('data', type=str, help='Script Data or data file')
parser.add_argument('--start', type=str, help='Script Start')
parser.add_argument('--end', type=str, help='Script End')
parser.add_argument('--description', type=str,
help='Script Description')
return parser
@@ -114,10 +107,6 @@ class CliUpdateScript(BaseScriptCli):
parser.add_argument('-n', '--name', type=str, help='Script Name')
parser.add_argument('-d', '--data', type=str,
help='Script Data or data file')
parser.add_argument('--start', type=str, help='Script Start')
parser.add_argument('--end', type=str, help='Script End')
parser.add_argument('--description', type=str,
help='Script Description')
return parser

View File

@@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from oslo_utils import strutils
from cloudkittyclient.common import base
from cloudkittyclient import exc
from distutils.util import strtobool
class ScopeManager(base.BaseManager):
"""Class used to handle /v2/scope endpoint"""
@@ -133,8 +133,7 @@ class ScopeManager(base.BaseManager):
)
if kwargs.get('active'):
body['active'] = strutils.bool_from_string(
kwargs.get('active'), strict=True)
body['active'] = strtobool(kwargs.get('active'))
# Stripping None
body = dict(filter(lambda elem: elem[1] is not None, body.items()))

View File

@@ -35,20 +35,10 @@ class CliSummaryGet(lister.Lister):
help='Maximal number of elements')
parser.add_argument('-g', '--groupby', type=str, action='append',
help='Attribute to group the summary by. Can be '
'specified several times. One can also group '
'by different time options such as: "time-d" '
'to group by day of the year, "time-w" to '
'group by week of the year, "time-m" to '
'group by month, and "time-y" to group data '
'by year.')
'specified several times')
parser.add_argument('--filter', type=filter_, action='append',
help="Optional filter, in 'key:value' format. Can "
"be specified several times. It is also "
"possible to filter data using the group by "
"values. However, one needs to group by as "
"well; for instance, if one wants to filter "
"by resource id (id), then we need to group "
"by id via the option '-g id'.")
"be specified several times.")
parser.add_argument('-b', '--begin', type=timeutils.parse_isotime,
help="Start of the period to query, in iso8601 "
"format. Example: 2019-05-01T00:00:00Z.")

View File

@@ -48,8 +48,9 @@ project = 'python-cloudkittyclient'
copyright = '2017, OpenStack Foundation'
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/python-cloudkittyclient'
openstackdocs_use_storyboard = True
repository_name = 'openstack/python-cloudkittyclient'
bug_project = 'cloudkitty'
bug_tag = 'python-cloudkittyclient'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True

View File

@@ -42,17 +42,17 @@ Version
-------
Two versions of the client exist: v1 and v2. The v2 version adds support for
v2 API endpoints. The default API version is 2. You can specify which API
v2 API endpoints. The default API version is 1. You can specify which API
version you want to use via a CLI option:
.. code-block:: shell
# EITHER
cloudkitty --os-rating-api-version 1 module list
cloudkitty --os-rating-api-version 2 summary get
# OR
export OS_RATING_API_VERSION=1
cloudkitty module list
export OS_RATING_API_VERSION=2
cloudkitty summary get
Again, the option can also be provided to the OSC plugin, both via the CLI
flag or the environment variable.
@@ -68,7 +68,7 @@ to use it without keystone authentication, cloudkittyclient provides the
>>> from cloudkittyclient import auth as ck_auth
>>> auth = ck_auth.CloudKittyNoAuthPlugin(endpoint='http://127.0.0.1:8889')
>>> client = ck_client.Client('2', auth=auth)
>>> client = ck_client.Client('1', auth=auth)
>>> client.report.get_summary()
{u'summary': [{u'begin': u'2018-03-01T00:00:00',
u'end': u'2018-04-01T00:00:00',
@@ -95,7 +95,7 @@ Else, use it the same way as any other OpenStack client::
>>> ck_session = session.Session(auth=auth)
>>> c = ck_client.Client('2', session=ck_session)
>>> c = ck_client.Client('1', session=ck_session)
>>> c.report.get_summary()
{u'summary': [{u'begin': u'2018-03-01T00:00:00',
@@ -112,25 +112,25 @@ Else, use it the same way as any other OpenStack client::
and ``cacert``::
>>> client = ck_client.Client(
'2', auth=auth, insecure=False, cacert='/path/to/ca')
'1', auth=auth, insecure=False, cacert='/path/to/ca')
If you want to use the v1 API, you have to specify it at client instanciation
If you want to use the v2 API, you have to specify it at client instanciation
.. code-block:: python
c = ck_client.Client('1', session=session)
c = ck_client.Client('2', session=session)
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``::
$ cloudkitty --debug --os-auth-type cloudkitty-noauth summary get
+---------------------------+---------------------------+------------+-------------------+
| Begin | End | Qty | Rate |
+---------------------------+---------------------------+------------+-------------------+
| 2025-12-01T00:00:00+01:00 | 2026-01-01T00:00:00+01:00 | 21662194.0 | 3618130.211340219 |
+---------------------------+---------------------------+------------+-------------------+
+------------+---------------+------------+---------------------+---------------------+
| Project ID | Resource Type | Rate | Begin Time | End Time |
+------------+---------------+------------+---------------------+---------------------+
| ALL | ALL | 1676.95499 | 2018-03-01T00:00:00 | 2018-04-01T00:00:00 |
+------------+---------------+------------+---------------------+---------------------+
CSV report generation

View File

@@ -1,8 +0,0 @@
---
upgrade:
- |
The default API version has been changed from v1 to v2. Users who want
to continue using the v1 API must now explicitly specify the API version
using the ``--os-rating-api-version 1`` CLI option or by setting the
``OS_RATING_API_VERSION=1`` environment variable. If no version is
specified, the client will now use the v2 API by default.

View File

@@ -1,5 +0,0 @@
---
upgrade:
- |
Support for Python 3.9 has been removed. Now Python 3.10 is the minimum
version supported.

View File

@@ -3,4 +3,4 @@
===========================
.. release-notes::
:branch: unmaintained/2023.1
:branch: stable/2023.1

View File

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

View File

@@ -1,6 +0,0 @@
===========================
2024.1 Series Release Notes
===========================
.. release-notes::
:branch: unmaintained/2024.1

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,12 +8,6 @@ Contents
:maxdepth: 2
unreleased
2026.1
2025.2
2025.1
2024.2
2024.1
2023.2
2023.1
zed
yoga

View File

@@ -3,4 +3,4 @@ Victoria Series Release Notes
=============================
.. release-notes::
:branch: unmaintained/victoria
:branch: stable/victoria

View File

@@ -3,4 +3,4 @@ Wallaby Series Release Notes
============================
.. release-notes::
:branch: unmaintained/wallaby
:branch: stable/wallaby

View File

@@ -3,4 +3,4 @@ Xena Series Release Notes
=========================
.. release-notes::
:branch: unmaintained/xena
:branch: stable/xena

View File

@@ -3,4 +3,4 @@ Yoga Series Release Notes
=========================
.. release-notes::
:branch: unmaintained/yoga
:branch: stable/yoga

View File

@@ -3,4 +3,4 @@ Zed Series Release Notes
========================
.. release-notes::
:branch: unmaintained/zed
:branch: stable/zed

View File

@@ -2,6 +2,10 @@
# date but we do not test them so no guarantee of having them all correct. If
# you find any incorrect lower bounds, let us know or propose a fix.
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=5.5.1 # Apache-2.0
cliff>=3.5.0 # Apache-2.0
keystoneauth1>=4.3.0 # Apache-2.0
@@ -9,5 +13,5 @@ oslo.utils>=4.7.0 # Apache-2.0
oslo.log>=4.4.0 # Apache-2.0
PyYAML>=5.3.1 # MIT
jsonpath-rw-ext>=1.2.0 # Apache-2.0
openstacksdk>=0.10.0 # Apache-2.0
os-client-config>=2.1.0 # Apache-2.0
osc-lib>=2.3.0 # Apache-2.0

View File

@@ -6,7 +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.10
python_requires = >=3.6
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -17,10 +17,10 @@ classifier =
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: 3
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: 3.13
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
[files]
packages =

View File

@@ -1,4 +1,14 @@
hacking>=7.0.0,<7.1.0 # Apache-2.0
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking>=3.0.1,<3.1.0 # Apache-2.0
# remove this pyflakes from here once you bump the
# hacking to 3.2.0 or above. hacking 3.2.0 takes
# care of pyflakes version compatibilty.
pyflakes>=2.1.1
coverage>=4.0,!=4.4 # Apache-2.0
python-subunit>=1.4.0 # Apache-2.0/BSD
oslotest>=1.10.0 # Apache-2.0

12
tox.ini
View File

@@ -1,18 +1,23 @@
[tox]
minversion = 3.18.0
envlist = py3,pep8
skipsdist = True
ignore_basepython_conflict = True
[testenv]
basepython = python3
usedevelop = True
install_command = pip install -U {opts} {packages}
setenv =
DEVSTACK_VENV={env:DEVSTACK_VENV}
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands = stestr run {posargs}
[testenv:cover]
setenv =
VIRTUAL_ENV={envdir}
PYTHON=coverage run --source cloudkittyclient --parallel-mode
commands =
stestr run {posargs}
@@ -38,6 +43,7 @@ passenv =
OS_AUTH_URL
OS_USERNAME
OS_ENDPOINT
DEVSTACK_VENV
VIRTUAL_ENV
setenv = OS_RATING_API_VERSION=1
commands = stestr run --concurrency=1 --test-path ./cloudkittyclient/tests/functional/v1
@@ -56,6 +62,7 @@ passenv =
OS_AUTH_URL
OS_USERNAME
OS_ENDPOINT
DEVSTACK_VENV
VIRTUAL_ENV
setenv = OS_RATING_API_VERSION=2
commands = stestr run --concurrency=1 --test-path ./cloudkittyclient/tests/functional/v2
@@ -68,11 +75,12 @@ commands = {posargs}
[testenv:docs]
deps =
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.2}
-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}
allowlist_externals =
make
@@ -93,7 +101,7 @@ import_exceptions = cloudkittyclient.i18n
[testenv:releasenotes]
deps =
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.2}
-r{toxinidir}/doc/requirements.txt
commands =
sphinx-build -a -E -W -d releasenotes/build/doctrees --keep-going -b html releasenotes/source releasenotes/build/html