Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e07c2951b8 | ||
| ce9910e38e | |||
| c1d2a93b48 | |||
| 97dc4d64da | |||
| 0c97e40e2b | |||
|
|
0ee5e17ee5 | ||
|
|
07d4e86ca4 | ||
|
|
6bd44e7413 | ||
|
|
c30878e414 | ||
|
|
eb0cac7148 | ||
|
|
187b0ce70c | ||
|
|
277b47779f | ||
|
|
19c0ebad5b | ||
| de6c8b22c5 |
@@ -2,3 +2,4 @@
|
||||
host=review.opendev.org
|
||||
port=29418
|
||||
project=openstack/python-cloudkittyclient.git
|
||||
defaultbranch=stable/2023.1
|
||||
|
||||
@@ -43,10 +43,9 @@
|
||||
|
||||
- project:
|
||||
templates:
|
||||
- openstack-lower-constraints-jobs
|
||||
- check-requirements
|
||||
- openstack-cover-jobs
|
||||
- openstack-python3-yoga-jobs
|
||||
- openstack-python3-jobs
|
||||
- openstackclient-plugin-jobs
|
||||
- publish-openstack-docs-pti
|
||||
- release-notes-jobs-python3
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
from cloudkittyclient.v1 import client
|
||||
from cloudkittyclient.v2 import dataframes
|
||||
from cloudkittyclient.v2.rating import modules
|
||||
from cloudkittyclient.v2 import reprocessing
|
||||
from cloudkittyclient.v2 import scope
|
||||
from cloudkittyclient.v2 import summary
|
||||
|
||||
@@ -42,3 +43,4 @@ class Client(client.Client):
|
||||
self.scope = scope.ScopeManager(self.api_client)
|
||||
self.summary = summary.SummaryManager(self.api_client)
|
||||
self.rating = modules.RatingManager(self.api_client)
|
||||
self.reprocessing = reprocessing.ReprocessingManager(self.api_client)
|
||||
|
||||
76
cloudkittyclient/v2/reprocessing.py
Normal file
76
cloudkittyclient/v2/reprocessing.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# 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.common import base
|
||||
from cloudkittyclient import exc
|
||||
|
||||
|
||||
class ReprocessingManager(base.BaseManager):
|
||||
"""Class used to handle /v2/task/reprocesses endpoint"""
|
||||
|
||||
url = '/v2/task/reprocesses'
|
||||
|
||||
def get_reprocessing_tasks(self, offset=0, limit=100, scope_ids=[],
|
||||
order="DESC", **kwargs):
|
||||
"""Returns a paginated list of reprocessing tasks.
|
||||
|
||||
Some optional filters can be provided.
|
||||
|
||||
:param offset: Index of the first reprocessing task
|
||||
that should be returned.
|
||||
:type offset: int
|
||||
:param limit: Maximal number of reprocessing task to return.
|
||||
:type limit: int
|
||||
:param scope_ids: Optional scope_ids to filter on.
|
||||
:type scope_ids: list of str
|
||||
:param order: Optional order (asc/desc) to sort tasks.
|
||||
:type order: str
|
||||
"""
|
||||
kwargs = kwargs or {}
|
||||
kwargs['order'] = order
|
||||
kwargs['offset'] = offset
|
||||
kwargs['limit'] = limit
|
||||
|
||||
authorized_args = ['offset', 'limit', 'order']
|
||||
url = self.get_url(None, kwargs, authorized_args=authorized_args)
|
||||
|
||||
if scope_ids:
|
||||
url += "&scope_ids=%s" % (",".join(scope_ids))
|
||||
return self.api_client.get(url).json()
|
||||
|
||||
def post_reprocessing_task(self, scope_ids=[], start=None, end=None,
|
||||
reason=None, **kwargs):
|
||||
"""Creates a reprocessing task
|
||||
|
||||
:param start: The start date of the reprocessing task
|
||||
:type start: timeutils.parse_isotime
|
||||
:param end: The end date of the reprocessing task
|
||||
:type end: timeutils.parse_isotime
|
||||
:param scope_ids: The scope IDs to create the reprocessing task to
|
||||
:type scope_ids: list of str
|
||||
:param reason: The reason for the reprocessing task
|
||||
:type reason: str
|
||||
"""
|
||||
|
||||
if not scope_ids:
|
||||
raise exc.ArgumentRequired("'scope-id' argument is required")
|
||||
|
||||
body = dict(
|
||||
scope_ids=scope_ids,
|
||||
start_reprocess_time=start,
|
||||
end_reprocess_time=end,
|
||||
reason=reason
|
||||
)
|
||||
|
||||
body = dict(filter(lambda elem: bool(elem[1]), body.items()))
|
||||
|
||||
return self.api_client.post(self.url, json=body).json()
|
||||
95
cloudkittyclient/v2/reprocessing_cli.py
Normal file
95
cloudkittyclient/v2/reprocessing_cli.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# 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 oslo_utils import timeutils
|
||||
|
||||
from cloudkittyclient import utils
|
||||
|
||||
|
||||
class CliReprocessingTasksGet(lister.Lister):
|
||||
"""Get reprocessing tasks."""
|
||||
|
||||
result_columns = [
|
||||
('scope_id', 'Scope ID'),
|
||||
('reason', 'Reason'),
|
||||
('start_reprocess_time', 'Start reprocessing time'),
|
||||
('end_reprocess_time', 'End reprocessing time'),
|
||||
('current_reprocess_time', 'Current reprocessing time'),
|
||||
]
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliReprocessingTasksGet, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument('--scope-id', type=str, default=[],
|
||||
action='append', help='Optional filter on scope '
|
||||
'IDs. This filter can be '
|
||||
'used multiple times.')
|
||||
|
||||
parser.add_argument('--offset', type=int, default=0,
|
||||
help='Index of the first scope. '
|
||||
'The default value is 0.')
|
||||
parser.add_argument('--limit', type=int, default=100,
|
||||
help='Maximal number of scopes. '
|
||||
'The default value is 100.')
|
||||
parser.add_argument('--order', type=str, default="DESC",
|
||||
help='The order to sort the reprocessing tasks '
|
||||
'(ASC or DESC).')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
resp = utils.get_client_from_osc(
|
||||
self).reprocessing.get_reprocessing_tasks(
|
||||
scope_ids=parsed_args.scope_id, offset=parsed_args.offset,
|
||||
limit=parsed_args.limit, order=parsed_args.order
|
||||
)
|
||||
|
||||
values = utils.list_to_cols(resp['results'], self.result_columns)
|
||||
return [col[1] for col in self.result_columns], values
|
||||
|
||||
|
||||
class CliReprocessingTasksPost(lister.Lister):
|
||||
"""Create a reprocessing task."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliReprocessingTasksPost, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument('--scope-id', type=str, default=[],
|
||||
action='append',
|
||||
help='The scope IDs to reprocess. This option can '
|
||||
'be used multiple times to execute the same '
|
||||
'reprocessing task for different scope IDs.')
|
||||
|
||||
parser.add_argument('--start-reprocess-time',
|
||||
type=timeutils.parse_isotime,
|
||||
help="Start of the period to reprocess in ISO8601 "
|
||||
"format. Example: '2022-04-22T00:00:00Z.'")
|
||||
|
||||
parser.add_argument('--end-reprocess-time',
|
||||
type=timeutils.parse_isotime,
|
||||
help="End of the period to reprocess in ISO8601 "
|
||||
"format. Example: '2022-04-22T00:00:00Z.'")
|
||||
|
||||
parser.add_argument('--reason', type=str,
|
||||
help="The reason to create the reprocessing task.")
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
return ["Result"], utils.get_client_from_osc(
|
||||
self).reprocessing.post_reprocessing_task(
|
||||
scope_ids=parsed_args.scope_id,
|
||||
start=parsed_args.start_reprocess_time,
|
||||
end=parsed_args.end_reprocess_time,
|
||||
reason=parsed_args.reason
|
||||
)
|
||||
@@ -15,6 +15,8 @@
|
||||
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"""
|
||||
@@ -100,3 +102,41 @@ class ScopeManager(base.BaseManager):
|
||||
|
||||
url = self.get_url(None, kwargs)
|
||||
return self.api_client.put(url, json=body)
|
||||
|
||||
def update_scope(self, **kwargs):
|
||||
"""Update storage scope
|
||||
|
||||
The `scope_id field` is mandatory, and all other are optional. Only the
|
||||
attributes sent will be updated. The attributes that are not sent will
|
||||
not be changed in the backend.
|
||||
|
||||
:param collector: collector to be used by the scope.
|
||||
:type collector: str
|
||||
:param fetcher: fetcher to be used by the scope.
|
||||
:type fetcher: str
|
||||
:param scope_id: Mandatory scope_id to update.
|
||||
:type scope_id: str
|
||||
:param scope_key: scope_key to be used by the scope.
|
||||
:type scope_key: str
|
||||
:param active: Indicates if the scope is active or not
|
||||
:type active: str
|
||||
"""
|
||||
|
||||
if not kwargs.get('scope_id'):
|
||||
raise exc.ArgumentRequired("'scope_id' argument is required")
|
||||
|
||||
body = dict(
|
||||
scope_id=kwargs.get('scope_id'),
|
||||
scope_key=kwargs.get('scope_key'),
|
||||
collector=kwargs.get('collector'),
|
||||
fetcher=kwargs.get('fetcher')
|
||||
)
|
||||
|
||||
if kwargs.get('active'):
|
||||
body['active'] = strtobool(kwargs.get('active'))
|
||||
|
||||
# Stripping None
|
||||
body = dict(filter(lambda elem: elem[1] is not None, body.items()))
|
||||
|
||||
url = self.get_url(None, kwargs)
|
||||
return self.api_client.patch(url, json=body).json()
|
||||
|
||||
@@ -96,3 +96,36 @@ class CliScopeStateReset(command.Command):
|
||||
all_scopes=parsed_args.all_scopes,
|
||||
state=parsed_args.state,
|
||||
)
|
||||
|
||||
|
||||
class CliPatchScope(command.Command):
|
||||
"""Update scope attributes."""
|
||||
|
||||
info_columns = [
|
||||
('scope_key', 'Scope Key'),
|
||||
('collector', 'Collector'),
|
||||
('fetcher', 'Fetcher'),
|
||||
('active', 'Active'),
|
||||
]
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliPatchScope, self).get_parser(prog_name)
|
||||
|
||||
for col in self.info_columns:
|
||||
parser.add_argument(
|
||||
'--' + col[0].replace('_', '-'), type=str,
|
||||
help='Optional filter on ' + col[1])
|
||||
|
||||
parser.add_argument(
|
||||
'-id', '--scope-id', required=True, type=str,
|
||||
help="The scope ID to be updated")
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
return utils.get_client_from_osc(self).scope.update_scope(
|
||||
collector=parsed_args.collector,
|
||||
fetcher=parsed_args.fetcher,
|
||||
scope_id=parsed_args.scope_id,
|
||||
scope_key=parsed_args.scope_key,
|
||||
active=parsed_args.active)
|
||||
|
||||
@@ -44,8 +44,8 @@ source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'python-cloudkittyclient'
|
||||
copyright = u'2017, OpenStack Foundation'
|
||||
project = 'python-cloudkittyclient'
|
||||
copyright = '2017, OpenStack Foundation'
|
||||
|
||||
# openstackdocstheme options
|
||||
repository_name = 'openstack/python-cloudkittyclient'
|
||||
@@ -99,8 +99,8 @@ latex_elements = {
|
||||
latex_documents = [
|
||||
('index',
|
||||
'doc-%s.tex' % project,
|
||||
u'%s Documentation' % project,
|
||||
u'OpenStack Foundation', 'howto', True),
|
||||
'%s Documentation' % project,
|
||||
'OpenStack Foundation', 'howto', True),
|
||||
]
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# requirements
|
||||
pbr==5.5.1 # Apache-2.0
|
||||
cliff==3.5.0 # Apache-2.0
|
||||
keystoneauth1==4.3.0 # Apache-2.0
|
||||
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
|
||||
os-client-config==2.1.0 # Apache-2.0
|
||||
osc-lib==2.3.0 # Apache-2.0
|
||||
|
||||
# test-requirements.txt
|
||||
pyflakes==2.1.1
|
||||
coverage==4.0 # Apache-2.0
|
||||
python-subunit==1.4.0 # Apache-2.0/BSD
|
||||
oslotest==1.10.0 # Apache-2.0
|
||||
stestr==2.0 # Apache-2.0
|
||||
python-openstackclient==3.14 # Apache-2.0
|
||||
|
||||
# doc/requirements.txt
|
||||
openstackdocstheme==1.30.0 # Apache-2.0
|
||||
sphinx==1.6.2 # BSD
|
||||
reno==2.5.0 # Apache2
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Introduce the patch scope API in the CLI. The command "rating scope
|
||||
patch" is added to the OpenStack CLI with this patch, and the command
|
||||
"scope patch" is added to the CloudKitty python client.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Introduce reprocessing task API in the CLI. The following new commands
|
||||
are added to the OpenStack CLI "rating tasks reprocessing get" and
|
||||
"rating tasks reprocessing create". For CloudKitty CLI, we added the
|
||||
following new commands "tasks reprocessing get" and "tasks reprocessing
|
||||
create". Both command sets work in a similar fashion, but one is
|
||||
targetting the OpenStack CLI integration, whereas the other is
|
||||
targetting CloudKitty client only.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixed a bug where creating a reprocessing task would fail due to sending a
|
||||
POST request to the wrong endpoint.
|
||||
@@ -42,8 +42,8 @@ source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'CloudKitty Client Release Notes'
|
||||
copyright = u'2016, CloudKitty developers'
|
||||
project = 'CloudKitty Client Release Notes'
|
||||
copyright = '2016, CloudKitty developers'
|
||||
|
||||
# Release notes are version independent.
|
||||
# The short X.Y version.
|
||||
@@ -194,8 +194,8 @@ latex_elements = {
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'PythonCloudKittyClient.tex',
|
||||
u'CloudKitty Client Release Notes Documentation',
|
||||
u'CloudKitty developers', 'manual'),
|
||||
'CloudKitty Client Release Notes Documentation',
|
||||
'CloudKitty developers', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -225,8 +225,8 @@ latex_documents = [
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'cloudkittyclient',
|
||||
u'CloudKitty Client Release Notes Documentation',
|
||||
[u'CloudKitty developers'], 1)
|
||||
'CloudKitty Client Release Notes Documentation',
|
||||
['CloudKitty developers'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
@@ -240,8 +240,8 @@ man_pages = [
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'cloudkittyclient',
|
||||
u'CloudKitty Client Release Notes Documentation',
|
||||
u'CloudKitty Client developers', 'CloudKittyClient',
|
||||
'CloudKitty Client Release Notes Documentation',
|
||||
'CloudKitty Client developers', 'CloudKittyClient',
|
||||
'One line description of project.', 'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ Contents
|
||||
:maxdepth: 2
|
||||
|
||||
unreleased
|
||||
zed
|
||||
yoga
|
||||
xena
|
||||
wallaby
|
||||
victoria
|
||||
|
||||
6
releasenotes/source/yoga.rst
Normal file
6
releasenotes/source/yoga.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
=========================
|
||||
Yoga Series Release Notes
|
||||
=========================
|
||||
|
||||
.. release-notes::
|
||||
:branch: stable/yoga
|
||||
6
releasenotes/source/zed.rst
Normal file
6
releasenotes/source/zed.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
========================
|
||||
Zed Series Release Notes
|
||||
========================
|
||||
|
||||
.. release-notes::
|
||||
:branch: stable/zed
|
||||
@@ -1,3 +1,7 @@
|
||||
# Requirements lower bounds listed here are our best effort to keep them up to
|
||||
# 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.
|
||||
|
||||
@@ -89,11 +89,15 @@ openstack.rating.v1 =
|
||||
rating_pyscript_delete = cloudkittyclient.v1.rating.pyscripts_cli:CliDeleteScript
|
||||
|
||||
openstack.rating.v2 =
|
||||
rating_tasks_reprocessing_get = cloudkittyclient.v2.reprocessing_cli:CliReprocessingTasksGet
|
||||
rating_tasks_reprocessing_create = cloudkittyclient.v2.reprocessing_cli:CliReprocessingTasksPost
|
||||
|
||||
rating_dataframes_get = cloudkittyclient.v2.dataframes_cli:CliDataframesGet
|
||||
rating_dataframes_add = cloudkittyclient.v2.dataframes_cli:CliDataframesAdd
|
||||
|
||||
rating_scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet
|
||||
rating_scope_state_reset = cloudkittyclient.v2.scope_cli:CliScopeStateReset
|
||||
rating_scope_patch = cloudkittyclient.v2.scope_cli:CliPatchScope
|
||||
|
||||
rating_summary_get = cloudkittyclient.v2.summary_cli:CliSummaryGet
|
||||
|
||||
@@ -205,11 +209,15 @@ cloudkittyclient_v1 =
|
||||
pyscript_delete = cloudkittyclient.v1.rating.pyscripts_cli:CliDeleteScript
|
||||
|
||||
cloudkittyclient_v2 =
|
||||
tasks_reprocessing_get = cloudkittyclient.v2.reprocessing_cli:CliReprocessingTasksGet
|
||||
tasks_reprocessing_create = cloudkittyclient.v2.reprocessing_cli:CliReprocessingTasksPost
|
||||
|
||||
dataframes_add = cloudkittyclient.v2.dataframes_cli:CliDataframesAdd
|
||||
dataframes_get = cloudkittyclient.v2.dataframes_cli:CliDataframesGet
|
||||
|
||||
scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet
|
||||
scope_state_reset = cloudkittyclient.v2.scope_cli:CliScopeStateReset
|
||||
scope_patch = cloudkittyclient.v2.scope_cli:CliPatchScope
|
||||
|
||||
summary_get = cloudkittyclient.v2.summary_cli:CliSummaryGet
|
||||
|
||||
|
||||
10
tox.ini
10
tox.ini
@@ -46,7 +46,7 @@ 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.1}
|
||||
-r{toxinidir}/doc/requirements.txt
|
||||
commands = sphinx-build --keep-going -b html doc/source doc/build/html
|
||||
|
||||
@@ -72,13 +72,7 @@ import_exceptions = cloudkittyclient.i18n
|
||||
|
||||
[testenv:releasenotes]
|
||||
deps =
|
||||
-c{env:TOX_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
|
||||
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.1}
|
||||
-r{toxinidir}/doc/requirements.txt
|
||||
commands =
|
||||
sphinx-build -a -E -W -d releasenotes/build/doctrees --keep-going -b html releasenotes/source releasenotes/build/html
|
||||
|
||||
[testenv:lower-constraints]
|
||||
deps =
|
||||
-c{toxinidir}/lower-constraints.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
-r{toxinidir}/requirements.txt
|
||||
|
||||
Reference in New Issue
Block a user