diff --git a/codegenerator/common/__init__.py b/codegenerator/common/__init__.py index 09c703f..877f6c5 100644 --- a/codegenerator/common/__init__.py +++ b/codegenerator/common/__init__.py @@ -20,7 +20,7 @@ import yaml from openapi_core import Spec from pydantic import BaseModel -VERSION_RE = re.compile(r"[Vv][0-9.]*") +VERSION_RE = re.compile(r"^[Vv]([0-9]+)(\.([0-9]+))?$") # RE to split name from camelCase or by [`:`,`_`,`-`] SPLIT_NAME_RE = re.compile(r"(?<=[a-z])(?=[A-Z])|:|_|-") diff --git a/codegenerator/common/rust.py b/codegenerator/common/rust.py index 333e334..29151d5 100644 --- a/codegenerator/common/rust.py +++ b/codegenerator/common/rust.py @@ -978,6 +978,8 @@ class TypeManager: """Return static lifetimes of the Structure""" lifetimes = request_model.lifetimes for param in self.parameters.values(): + if param.location == "header": + continue lt = param.lifetimes if lt: lifetimes.update(lt) diff --git a/codegenerator/rust_sdk.py b/codegenerator/rust_sdk.py index 2dfa942..c1256a5 100644 --- a/codegenerator/rust_sdk.py +++ b/codegenerator/rust_sdk.py @@ -367,6 +367,16 @@ class RustSdkGenerator(BaseGenerator): spec, args.operation_name ) + api_ver_matches: re.Match | None = None + path_elements = path.lstrip("/").split("/") + api_ver: dict[str, int] = {} + ver_prefix: str | None = None + if path_elements: + api_ver_matches = re.match(common.VERSION_RE, path_elements[0]) + if api_ver_matches and api_ver_matches.groups(): + # Remember the version prefix to discard it in the template + ver_prefix = path_elements[0] + for operation_variant in operation_variants: logging.debug("Processing variant %s" % operation_variant) # TODO(gtema): if we are in MV variants filter out unsupported query @@ -374,6 +384,14 @@ class RustSdkGenerator(BaseGenerator): # TODO(gtema): previously we were ensuring `router_id` path param # is renamed to `id` + if api_ver_matches: + api_ver = { + "major": api_ver_matches.group(1), + "minor": api_ver_matches.group(3) or 0, + } + else: + api_ver = {} + class_name = res_name.title() operation_body = operation_variant.get("body") type_manager = TypeManager() @@ -395,6 +413,13 @@ class RustSdkGenerator(BaseGenerator): min_ver = operation_body.get("x-openstack", {}).get("min-ver") if min_ver: mod_name += "_" + min_ver.replace(".", "") + v = min_ver.split(".") + if not len(v) == 2: + raise RuntimeError( + "Version information is not in format MAJOR.MINOR" + ) + api_ver = {"major": v[0], "minor": v[1]} + # There is request body. Get the ADT from jsonschema # if args.operation_type != "action": (_, all_types) = openapi_parser.parse( @@ -464,13 +489,14 @@ class RustSdkGenerator(BaseGenerator): sdk_service_name=common.get_rust_service_type_from_str( args.service_type ), - url=path[1:] if path.startswith("/") else path, + url=path.lstrip("/").lstrip(ver_prefix).lstrip("/"), method=method, type_manager=type_manager, response_key=response_key, response_list_item_key=args.response_list_item_key, mime_type=mime_type, is_json_patch=is_json_patch, + api_ver=api_ver, ) work_dir = Path(target_dir, "rust", "openstack_sdk", "src") diff --git a/codegenerator/templates/rust_sdk/impl.rs.j2 b/codegenerator/templates/rust_sdk/impl.rs.j2 index 61ee270..a2065ab 100644 --- a/codegenerator/templates/rust_sdk/impl.rs.j2 +++ b/codegenerator/templates/rust_sdk/impl.rs.j2 @@ -261,6 +261,13 @@ impl{{ type_manager.get_request_static_lifetimes(request) }} RestEndpoint for Re fn request_headers(&self) -> Option<&HeaderMap> { self._headers.as_ref() } +{%- if api_ver %} + + /// Returns required API version + fn api_version(&self) -> Option { + Some(ApiVersion::new({{ api_ver['major'] }}, {{ api_ver['minor'] }})) + } +{%- endif %} } {#- EP is pageable if operation_type is list and there is limit or marker query parameter #}