Merge "Add API to create scopes"

This commit is contained in:
Zuul 2022-07-08 13:56:32 +00:00 committed by Gerrit Code Review
commit f9d2ff341b
7 changed files with 197 additions and 11 deletions

View File

@ -183,7 +183,10 @@ class ScopeState(base.BaseResource):
voluptuous.Required('scope_key'): vutils.get_string_type(),
voluptuous.Required('fetcher'): vutils.get_string_type(),
voluptuous.Required('collector'): vutils.get_string_type(),
# This "state" property should be removed in the next release.
voluptuous.Required('state'): vutils.get_string_type(),
voluptuous.Optional('last_processed_timestamp'):
voluptuous.Coerce(tzutils.dt_from_iso),
voluptuous.Required('active'): bool,
voluptuous.Required('scope_activation_toggle_date'):
vutils.get_string_type()
@ -226,6 +229,79 @@ class ScopeState(base.BaseResource):
'fetcher': update_storage_scope.fetcher,
'collector': update_storage_scope.collector,
'state': update_storage_scope.state.isoformat(),
'last_processed_timestamp':
update_storage_scope.last_processed_timestamp.isoformat(),
'active': update_storage_scope.active,
'scope_activation_toggle_date':
update_storage_scope.scope_activation_toggle_date.isoformat()
}
@api_utils.add_input_schema('body', {
voluptuous.Required('scope_id'):
api_utils.SingleQueryParam(str),
voluptuous.Optional('scope_key'):
api_utils.SingleQueryParam(str),
voluptuous.Optional('fetcher'):
api_utils.SingleQueryParam(str),
voluptuous.Optional('collector'):
api_utils.SingleQueryParam(str),
voluptuous.Optional('active'):
api_utils.SingleQueryParam(bool),
})
@api_utils.add_output_schema({
voluptuous.Required('scope_id'): vutils.get_string_type(),
voluptuous.Required('scope_key'): vutils.get_string_type(),
voluptuous.Required('fetcher'): vutils.get_string_type(),
voluptuous.Required('collector'): vutils.get_string_type(),
# This "state" property should be removed in the next release.
voluptuous.Required('state'): vutils.get_string_type(),
voluptuous.Optional('last_processed_timestamp'):
voluptuous.Coerce(tzutils.dt_from_iso),
voluptuous.Required('active'): bool,
voluptuous.Required('scope_activation_toggle_date'):
vutils.get_string_type()
})
def post(self, scope_id, scope_key=None, fetcher=None, collector=None,
active=None):
policy.authorize(
flask.request.context,
'scope:post_state',
{'tenant_id': scope_id or flask.request.context.project_id}
)
results = self._storage_state.get_all(identifier=scope_id)
if len(results) >= 1:
LOG.debug("There is already a scope with ID [%s], "
"scopes found: [%s].", scope_id, results)
raise http_exceptions.NotFound("Cannot create a scope with an "
"already existing scope_id: %s."
% scope_id)
LOG.debug("Creating storage scope with data: [scope_id=%s, "
"scope_key=%s, fetcher=%s, collector=%s, active=%s].",
scope_id, scope_key, fetcher, collector, active)
self._storage_state.create_scope(scope_id, None, fetcher=fetcher,
collector=collector,
scope_key=scope_key, active=active)
storage_scopes = self._storage_state.get_all(
identifier=scope_id)
update_storage_scope = storage_scopes[0]
last_processed_timestamp = None
if update_storage_scope.last_processed_timestamp.isoformat():
last_processed_timestamp =\
update_storage_scope.last_processed_timestamp.isoformat()
return {
'scope_id': update_storage_scope.identifier,
'scope_key': update_storage_scope.scope_key,
'fetcher': update_storage_scope.fetcher,
'collector': update_storage_scope.collector,
'state': last_processed_timestamp,
'last_processed_timestamp': last_processed_timestamp,
'active': update_storage_scope.active,
'scope_activation_toggle_date':
update_storage_scope.scope_activation_toggle_date.isoformat()

View File

@ -36,7 +36,12 @@ scope_policies = [
description='Enables operators to patch a storage scope',
operations=[{'path': '/v2/scope',
'method': 'PATCH'}]),
policy.DocumentedRuleDefault(
name='scope:post_state',
check_str=base.ROLE_ADMIN,
description='Enables operators to create a storage scope',
operations=[{'path': '/v2/scope',
'method': 'POST'}]),
]

View File

@ -168,6 +168,8 @@ class StateManager(object):
collector=None, scope_key=None):
"""Set the last processed timestamp of a scope.
If the scope does not exist yet in the database, it will create it.
:param identifier: Identifier of the scope
:type identifier: str
:param last_processed_timestamp: last processed timestamp of the scope
@ -191,18 +193,52 @@ class StateManager(object):
r.last_processed_timestamp = last_processed_timestamp
session.commit()
else:
state_object = self.model(
identifier=identifier,
last_processed_timestamp=last_processed_timestamp,
fetcher=fetcher,
collector=collector,
scope_key=scope_key,
)
session.add(state_object)
session.commit()
self.create_scope(identifier, last_processed_timestamp,
fetcher=fetcher, collector=collector,
scope_key=scope_key)
session.close()
def create_scope(self, identifier, last_processed_timestamp, fetcher=None,
collector=None, scope_key=None, active=True,
session=None):
"""Creates a scope in the database.
:param identifier: Identifier of the scope
:type identifier: str
:param last_processed_timestamp: last processed timestamp of the scope
:type last_processed_timestamp: datetime.datetime
:param fetcher: Fetcher associated to the scope
:type fetcher: str
:param collector: Collector associated to the scope
:type collector: str
:param scope_key: scope_key associated to the scope
:type scope_key: str
:param active: indicates if the scope is active
:type active: bool
:param session: the current database session to be reused
:type session: object
"""
is_session_reused = True
if not session:
session = db.get_session()
session.begin()
is_session_reused = False
state_object = self.model(
identifier=identifier,
last_processed_timestamp=last_processed_timestamp,
fetcher=fetcher,
collector=collector,
scope_key=scope_key,
active=active
)
session.add(state_object)
session.commit()
if not is_session_reused:
session.close()
def get_state(self, identifier,
fetcher=None, collector=None, scope_key=None):
LOG.warning("The method 'get_state' is deprecated."

View File

@ -109,6 +109,10 @@
# PATCH /v2/scope
#"scope:patch_state": "role:admin"
# Enables operators to create a storage scope
# POST /v2/scope
#"scope:post_state": "role:admin"
# Get a rating summary
# GET /v2/summary
#"summary:get_summary": "rule:admin_or_owner"

View File

@ -127,6 +127,56 @@ Response
- active: active_key_resp
Response Example
----------------
.. literalinclude:: ./api_samples/scope/scope_get.json
:language: javascript
Create a scope
================================
Create a scope.
.. rest_method:: POST /v2/scope
.. rest_parameters:: scope/scope_parameters.yml
- collector: collector
- fetcher: fetcher
- scope_id: scope_id
- scope_key: scope_key
- active: active_body
Status codes
------------
.. rest_status_code:: success http_status.yml
- 200
.. rest_status_code:: error http_status.yml
- 400
- 403
- 404
- 405
Response
--------
.. rest_parameters:: scope/scope_parameters.yml
- scope_id: scope_id_resp
- scope_key: scope_key_resp
- fetcher: fetcher_resp
- collector: collector_resp
- state: state
- last_processed_timestamp: last_processed_timestamp
- active: active_key_resp
- scope_activation_toggle_date: scope_activation_toggle_date
Response Example
----------------

View File

@ -88,6 +88,14 @@ last_processed_timestamp:
type: iso8601 timestamp
required: true
scope_activation_toggle_date:
in: body
description: |
It represents the last time the scope was activated/deactivated via the
PATCH API.
type: iso8601 timestamp
required: true
scope_id_body:
<<: *scope_id
in: body

View File

@ -0,0 +1,7 @@
---
features:
- |
Introduce an API to create scopes with a POST request. This is useful for
operators to register scopes before they are created as resources in the
collected backend and disable their processing without waiting for the
scopes to be discovered by CloudKitty.