From e1a6b90f7fca63c091eb27872255a3bd3688f2bb Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Thu, 13 Feb 2025 12:05:14 +0100 Subject: [PATCH] Hardcode barbican quota schemas Change-Id: Ida732b73f62ab5623edd8af571390debcf67facf --- codegenerator/openapi/barbican.py | 9 +- .../openapi/barbican_schemas/quota.py | 165 ++++++++++++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 codegenerator/openapi/barbican_schemas/quota.py diff --git a/codegenerator/openapi/barbican.py b/codegenerator/openapi/barbican.py index d72f16a..afd3606 100644 --- a/codegenerator/openapi/barbican.py +++ b/codegenerator/openapi/barbican.py @@ -22,6 +22,7 @@ from codegenerator.openapi.base import OpenStackServerSourceBase from codegenerator.openapi.utils import merge_api_ref_doc from codegenerator.openapi.barbican_schemas import container from codegenerator.openapi.barbican_schemas import order +from codegenerator.openapi.barbican_schemas import quota from codegenerator.openapi.barbican_schemas import secret from codegenerator.openapi.barbican_schemas import secret_store @@ -31,7 +32,7 @@ from ruamel.yaml.scalarstring import LiteralScalarString class BarbicanGenerator(OpenStackServerSourceBase): URL_TAG_MAP = {} - RESOURCE_MODULES = [container, order, secret, secret_store] + RESOURCE_MODULES = [container, order, quota, secret, secret_store] def __init__(self): pass @@ -478,6 +479,12 @@ class BarbicanGenerator(OpenStackServerSourceBase): ] and route.conditions.get("method", "GET") == ["PUT"]: # update order is not supported continue + if route.routelist == [ + "/v1/quotas/", + {"type": ":", "name": "quota_id"}, + ] and route.conditions.get("method", "GET") == ["GET"]: + # Get of the project quota is done using different URL + continue self._process_route(route, openapi_spec, framework="pecan") if args.api_ref_src: diff --git a/codegenerator/openapi/barbican_schemas/quota.py b/codegenerator/openapi/barbican_schemas/quota.py new file mode 100644 index 0000000..035564a --- /dev/null +++ b/codegenerator/openapi/barbican_schemas/quota.py @@ -0,0 +1,165 @@ +# 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 typing import Any + +from codegenerator.common.schema import ParameterSchema +from codegenerator.common.schema import TypeSchema + + +QUOTA_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": { + "secrets": { + "type": ["integer", "null"], + "description": "Contains the effective quota value of the current project for the secret resource.", + }, + "orders": { + "type": ["integer", "null"], + "description": "Contains the effective quota value of the current project for the orders resource.", + }, + "containers": { + "type": ["integer", "null"], + "description": "Contains the effective quota value of the current project for the containers resource.", + }, + "consumers": { + "type": ["integer", "null"], + "description": "Contains the effective quota value of the current project for the consumers resource.", + }, + "cas": { + "type": ["integer", "null"], + "description": "Contains the effective quota value of the current project for the CAs resource.", + }, + }, + "required": ["secrets", "orders", "containers", "consumers", "cas"], + "additionalProperties": False, +} + +QUOTAS_RESPONSE: dict[str, Any] = { + "type": "object", + "properties": { + "quotas": { + **QUOTA_SCHEMA, + "description": "Contains a dictionary with quota information", + } + }, + "required": ["quotas"], + "additionalProperties": False, +} + +PROJECT_QUOTA: dict[str, Any] = { + "type": "object", + "properties": { + "project_quotas": { + **QUOTA_SCHEMA, + "description": "Contains a dictionary with project quota information", + } + }, + "required": ["project_quotas"], + "additionalProperties": False, +} + +# Well, barbican itself use using crazy naming with project_quotas inside the project_quotas +PROJECT_QUOTAS: dict[str, Any] = { + "type": "object", + "properties": { + "project_id": { + "type": "string", + "description": "The UUID of a project with configured quota information.", + }, + **PROJECT_QUOTA["properties"], + }, + "required": ["project_quotas", "project_id"], + "additionalProperties": False, +} + + +PROJECT_QUOTAS_LIST_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": { + "next": { + "type": "string", + "description": "A HATEOAS URL to retrieve the next set of project quotas based on the offset and limit parameters. This attribute is only available when the total number of orders is greater than offset and limit parameter combined.", + }, + "previous": { + "type": "string", + "description": "A HATEOAS URL to retrieve the previous set of orders based on the offset and limit parameters. This attribute is only available when the request offset is greater than 0.", + }, + "total": { + "type": "integer", + "description": "The total number of orders available to the user.", + }, + "project_quotas": {"type": "array", "items": PROJECT_QUOTAS}, + }, + "required": ["project_quotas"], + "additionalProperties": False, +} + + +PROJECT_QUOTAS_LIST_PARAMETERS: dict[str, dict] = { + "quotas_offset": { + "in": "query", + "name": "offset", + "description": "The starting index within the total list of the orders that you would like to retrieve.", + "schema": {"type": "integer"}, + }, + "quotas_limit": { + "in": "query", + "name": "limit", + "description": "The maximum number of records to return (up to 100). The default limit is 10.", + "schema": {"type": "integer"}, + }, +} + + +def _post_process_operation_hook( + openapi_spec, operation_spec, path: str | None = None +): + """Hook to allow service specific generator to modify details""" + + operationId = operation_spec.operationId + if operationId == "project-quotas:get": + for key, val in PROJECT_QUOTAS_LIST_PARAMETERS.items(): + openapi_spec.components.parameters.setdefault( + key, ParameterSchema(**val) + ) + ref = f"#/components/parameters/{key}" + if ref not in [x.ref for x in operation_spec.parameters]: + operation_spec.parameters.append(ParameterSchema(ref=ref)) + + +def _get_schema_ref( + openapi_spec, name, description=None, schema_def=None, action_name=None +) -> tuple[str | None, str | None, bool]: + mime_type: str = "application/json" + ref: str + if name == "QuotasListResponse": + openapi_spec.components.schemas.setdefault( + name, TypeSchema(**QUOTA_SCHEMA) + ) + ref = f"#/components/schemas/{name}" + elif name == "Project_QuotasListResponse": + openapi_spec.components.schemas.setdefault( + name, TypeSchema(**PROJECT_QUOTAS_LIST_SCHEMA) + ) + ref = f"#/components/schemas/{name}" + elif name in ["Project_QuotaShowResponse", "Project_QuotaUpdateRequest"]: + openapi_spec.components.schemas.setdefault( + name, TypeSchema(**PROJECT_QUOTA) + ) + ref = f"#/components/schemas/{name}" + elif name == "Project_QuotaUpdateResponse": + return (None, None, True) + else: + return (None, None, False) + + return (ref, mime_type, True)