From 066aaaac0b2adf7247af047a9566073e29bb718d Mon Sep 17 00:00:00 2001 From: SDK Generator Bot Date: Fri, 13 Mar 2026 12:29:02 +0000 Subject: [PATCH] Generate ske --- services/ske/oas_commit | 2 +- services/ske/src/stackit/ske/__init__.py | 4 + .../ske/src/stackit/ske/api/default_api.py | 266 ++++++++++++++++++ services/ske/src/stackit/ske/api_client.py | 31 +- services/ske/src/stackit/ske/exceptions.py | 2 +- .../ske/src/stackit/ske/models/__init__.py | 3 +- services/ske/src/stackit/ske/models/access.py | 86 ++++++ .../ske/src/stackit/ske/models/cluster.py | 13 +- .../src/stackit/ske/models/cluster_error.py | 2 +- .../src/stackit/ske/models/cluster_status.py | 6 +- .../create_or_update_cluster_payload.py | 13 +- .../ske/src/stackit/ske/models/hibernation.py | 6 +- .../src/stackit/ske/models/idp_kubeconfig.py | 81 ++++++ .../ske/models/list_clusters_response.py | 6 +- .../src/stackit/ske/models/machine_image.py | 6 +- .../ske/models/machine_image_version.py | 6 +- .../ske/src/stackit/ske/models/nodepool.py | 6 +- .../stackit/ske/models/provider_options.py | 30 +- services/ske/src/stackit/ske/rest.py | 22 +- 19 files changed, 536 insertions(+), 55 deletions(-) create mode 100644 services/ske/src/stackit/ske/models/access.py create mode 100644 services/ske/src/stackit/ske/models/idp_kubeconfig.py diff --git a/services/ske/oas_commit b/services/ske/oas_commit index 85295bf53..e3713dde3 100644 --- a/services/ske/oas_commit +++ b/services/ske/oas_commit @@ -1 +1 @@ -9ba4c1ad01406fe6d0399b971043a2f9f74ea510 +0e64886dd0847341800d7191ed193b75413be998 diff --git a/services/ske/src/stackit/ske/__init__.py b/services/ske/src/stackit/ske/__init__.py index 9e61c70e9..1b2c7e0c8 100644 --- a/services/ske/src/stackit/ske/__init__.py +++ b/services/ske/src/stackit/ske/__init__.py @@ -29,6 +29,7 @@ "ApiAttributeError", "ApiException", "ACL", + "Access", "AccessScope", "AvailabilityZone", "CRI", @@ -45,6 +46,7 @@ "Hibernation", "HibernationSchedule", "IDP", + "IDPKubeconfig", "Image", "Kubeconfig", "Kubernetes", @@ -83,6 +85,7 @@ from stackit.ske.exceptions import ApiTypeError as ApiTypeError from stackit.ske.exceptions import ApiValueError as ApiValueError from stackit.ske.exceptions import OpenApiException as OpenApiException +from stackit.ske.models.access import Access as Access from stackit.ske.models.access_scope import AccessScope as AccessScope # import models into sdk package @@ -114,6 +117,7 @@ HibernationSchedule as HibernationSchedule, ) from stackit.ske.models.idp import IDP as IDP +from stackit.ske.models.idp_kubeconfig import IDPKubeconfig as IDPKubeconfig from stackit.ske.models.image import Image as Image from stackit.ske.models.kubeconfig import Kubeconfig as Kubeconfig from stackit.ske.models.kubernetes import Kubernetes as Kubernetes diff --git a/services/ske/src/stackit/ske/api/default_api.py b/services/ske/src/stackit/ske/api/default_api.py index 2ac00e743..50325e938 100644 --- a/services/ske/src/stackit/ske/api/default_api.py +++ b/services/ske/src/stackit/ske/api/default_api.py @@ -30,6 +30,7 @@ from stackit.ske.models.create_or_update_cluster_payload import ( CreateOrUpdateClusterPayload, ) +from stackit.ske.models.idp_kubeconfig import IDPKubeconfig from stackit.ske.models.kubeconfig import Kubeconfig from stackit.ske.models.list_clusters_response import ListClustersResponse from stackit.ske.models.login_kubeconfig import LoginKubeconfig @@ -1430,6 +1431,271 @@ def _get_cluster_serialize( _request_auth=_request_auth, ) + @validate_call + def get_idp_kubeconfig( + self, + project_id: StrictStr, + region: StrictStr, + cluster_name: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> IDPKubeconfig: + """Get a kubeconfig to authenticate via IDP for use with the STACKIT CLI + + A kubeconfig retrieved using this endpoint does not contain any credentials and instead obtains valid credentials via the STACKIT CLI. Permissions must be granted to the user beforehand using an admin kubeconfig. + + :param project_id: (required) + :type project_id: str + :param region: (required) + :type region: str + :param cluster_name: (required) + :type cluster_name: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_idp_kubeconfig_serialize( + project_id=project_id, + region=region, + cluster_name=cluster_name, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index, + ) + + _response_types_map: Dict[str, Optional[str]] = { + "200": "IDPKubeconfig", + "400": "object", + "401": "object", + "404": "object", + } + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + @validate_call + def get_idp_kubeconfig_with_http_info( + self, + project_id: StrictStr, + region: StrictStr, + cluster_name: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[IDPKubeconfig]: + """Get a kubeconfig to authenticate via IDP for use with the STACKIT CLI + + A kubeconfig retrieved using this endpoint does not contain any credentials and instead obtains valid credentials via the STACKIT CLI. Permissions must be granted to the user beforehand using an admin kubeconfig. + + :param project_id: (required) + :type project_id: str + :param region: (required) + :type region: str + :param cluster_name: (required) + :type cluster_name: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_idp_kubeconfig_serialize( + project_id=project_id, + region=region, + cluster_name=cluster_name, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index, + ) + + _response_types_map: Dict[str, Optional[str]] = { + "200": "IDPKubeconfig", + "400": "object", + "401": "object", + "404": "object", + } + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + @validate_call + def get_idp_kubeconfig_without_preload_content( + self, + project_id: StrictStr, + region: StrictStr, + cluster_name: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get a kubeconfig to authenticate via IDP for use with the STACKIT CLI + + A kubeconfig retrieved using this endpoint does not contain any credentials and instead obtains valid credentials via the STACKIT CLI. Permissions must be granted to the user beforehand using an admin kubeconfig. + + :param project_id: (required) + :type project_id: str + :param region: (required) + :type region: str + :param cluster_name: (required) + :type cluster_name: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_idp_kubeconfig_serialize( + project_id=project_id, + region=region, + cluster_name=cluster_name, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index, + ) + + _response_types_map: Dict[str, Optional[str]] = { + "200": "IDPKubeconfig", + "400": "object", + "401": "object", + "404": "object", + } + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + return response_data.response + + def _get_idp_kubeconfig_serialize( + self, + project_id, + region, + cluster_name, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = {} + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if project_id is not None: + _path_params["projectId"] = project_id + if region is not None: + _path_params["region"] = region + if cluster_name is not None: + _path_params["clusterName"] = cluster_name + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + # set the HTTP header `Accept` + if "Accept" not in _header_params: + _header_params["Accept"] = self.api_client.select_header_accept(["application/json"]) + + # authentication setting + _auth_settings: List[str] = [] + + return self.api_client.param_serialize( + method="GET", + resource_path="/v2/projects/{projectId}/regions/{region}/clusters/{clusterName}/kubeconfig/idp", + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth, + ) + @validate_call def get_login_kubeconfig( self, diff --git a/services/ske/src/stackit/ske/api_client.py b/services/ske/src/stackit/ske/api_client.py index f21e96585..8dbb35661 100644 --- a/services/ske/src/stackit/ske/api_client.py +++ b/services/ske/src/stackit/ske/api_client.py @@ -12,11 +12,13 @@ """ # noqa: E501 import datetime +import decimal import json import mimetypes import os import re import tempfile +import uuid from enum import Enum from typing import Dict, List, Optional, Tuple, Union from urllib.parse import quote @@ -63,8 +65,10 @@ class ApiClient: "bool": bool, "date": datetime.date, "datetime": datetime.datetime, + "decimal": decimal.Decimal, "object": object, } + _pool = None def __init__(self, configuration, header_name=None, header_value=None, cookie=None) -> None: self.config: Configuration = configuration @@ -267,7 +271,7 @@ def response_deserialize( return_data = self.__deserialize_file(response_data) elif response_type is not None: match = None - content_type = response_data.getheader("content-type") + content_type = response_data.headers.get("content-type") if content_type is not None: match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type) encoding = match.group(1) if match else "utf-8" @@ -284,7 +288,7 @@ def response_deserialize( return ApiResponse( status_code=response_data.status, data=return_data, - headers=response_data.getheaders(), + headers=response_data.headers, raw_data=response_data.data, ) @@ -296,6 +300,7 @@ def sanitize_for_serialization(self, obj): If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. @@ -311,12 +316,16 @@ def sanitize_for_serialization(self, obj): return obj.get_secret_value() elif isinstance(obj, self.PRIMITIVE_TYPES): return obj + elif isinstance(obj, uuid.UUID): + return str(obj) elif isinstance(obj, list): return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj] elif isinstance(obj, tuple): return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) elif isinstance(obj, dict): obj_dict = obj @@ -326,7 +335,7 @@ def sanitize_for_serialization(self, obj): # and attributes which value is not None. # Convert attribute name to json key in # model definition for request. - if hasattr(obj, "to_dict") and callable(obj.to_dict): + if hasattr(obj, "to_dict") and callable(getattr(obj, "to_dict")): obj_dict = obj.to_dict() else: obj_dict = obj.__dict__ @@ -354,7 +363,7 @@ def deserialize(self, response_text: str, response_type: str, content_type: Opti data = json.loads(response_text) except ValueError: data = response_text - elif re.match(r"^application/(json|[\w!#$&.+-^_]+\+json)\s*(;|$)", content_type, re.IGNORECASE): + elif re.match(r"^application/(json|[\w!#$&.+\-^_]+\+json)\s*(;|$)", content_type, re.IGNORECASE): if response_text == "": data = "" else: @@ -400,12 +409,14 @@ def __deserialize(self, data, klass): if klass in self.PRIMITIVE_TYPES: return self.__deserialize_primitive(data, klass) - elif klass == object: + elif klass is object: return self.__deserialize_object(data) - elif klass == datetime.date: + elif klass is datetime.date: return self.__deserialize_date(data) - elif klass == datetime.datetime: + elif klass is datetime.datetime: return self.__deserialize_datetime(data) + elif klass is decimal.Decimal: + return decimal.Decimal(data) elif issubclass(klass, Enum): return self.__deserialize_enum(data, klass) else: @@ -553,12 +564,14 @@ def __deserialize_file(self, response): os.close(fd) os.remove(path) - content_disposition = response.getheader("Content-Disposition") + content_disposition = response.headers.get("Content-Disposition") if content_disposition: m = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition) if m is None: raise ValueError("Unexpected 'content-disposition' header value") - filename = m.group(1) + filename = os.path.basename(m.group(1)) # Strip any directory traversal + if filename in ("", ".", ".."): # fall back to tmp filename + filename = os.path.basename(path) path = os.path.join(os.path.dirname(path), filename) with open(path, "wb") as f: diff --git a/services/ske/src/stackit/ske/exceptions.py b/services/ske/src/stackit/ske/exceptions.py index 0153ee5d2..7f4ae9acb 100644 --- a/services/ske/src/stackit/ske/exceptions.py +++ b/services/ske/src/stackit/ske/exceptions.py @@ -129,7 +129,7 @@ def __init__( self.body = http_resp.data.decode("utf-8") except Exception: # noqa: S110 pass - self.headers = http_resp.getheaders() + self.headers = http_resp.headers @classmethod def from_response( diff --git a/services/ske/src/stackit/ske/models/__init__.py b/services/ske/src/stackit/ske/models/__init__.py index 93fd8b4f0..52102c18d 100644 --- a/services/ske/src/stackit/ske/models/__init__.py +++ b/services/ske/src/stackit/ske/models/__init__.py @@ -12,7 +12,7 @@ Do not edit the class manually. """ # noqa: E501 - +from stackit.ske.models.access import Access from stackit.ske.models.access_scope import AccessScope # import models into model package @@ -36,6 +36,7 @@ from stackit.ske.models.hibernation import Hibernation from stackit.ske.models.hibernation_schedule import HibernationSchedule from stackit.ske.models.idp import IDP +from stackit.ske.models.idp_kubeconfig import IDPKubeconfig from stackit.ske.models.image import Image from stackit.ske.models.kubeconfig import Kubeconfig from stackit.ske.models.kubernetes import Kubernetes diff --git a/services/ske/src/stackit/ske/models/access.py b/services/ske/src/stackit/ske/models/access.py new file mode 100644 index 000000000..7e96d233f --- /dev/null +++ b/services/ske/src/stackit/ske/models/access.py @@ -0,0 +1,86 @@ +# coding: utf-8 + +""" + STACKIT Kubernetes Engine API + + The SKE API provides endpoints to create, update or delete clusters within STACKIT projects and to trigger further cluster management tasks. + + The version of the OpenAPI document: 2.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations + +import json +import pprint +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict +from typing_extensions import Self + +from stackit.ske.models.idp import IDP + + +class Access(BaseModel): + """ + Access + """ # noqa: E501 + + idp: Optional[IDP] = None + __properties: ClassVar[List[str]] = ["idp"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of Access from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of idp + if self.idp: + _dict["idp"] = self.idp.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of Access from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"idp": IDP.from_dict(obj["idp"]) if obj.get("idp") is not None else None}) + return _obj diff --git a/services/ske/src/stackit/ske/models/cluster.py b/services/ske/src/stackit/ske/models/cluster.py index c77601048..84a32f94c 100644 --- a/services/ske/src/stackit/ske/models/cluster.py +++ b/services/ske/src/stackit/ske/models/cluster.py @@ -20,6 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing_extensions import Annotated, Self +from stackit.ske.models.access import Access from stackit.ske.models.cluster_status import ClusterStatus from stackit.ske.models.extension import Extension from stackit.ske.models.hibernation import Hibernation @@ -34,6 +35,7 @@ class Cluster(BaseModel): Cluster """ # noqa: E501 + access: Optional[Access] = None extensions: Optional[Extension] = None hibernation: Optional[Hibernation] = None kubernetes: Kubernetes @@ -43,6 +45,7 @@ class Cluster(BaseModel): nodepools: Annotated[List[Nodepool], Field(min_length=1, max_length=50)] status: Optional[ClusterStatus] = None __properties: ClassVar[List[str]] = [ + "access", "extensions", "hibernation", "kubernetes", @@ -95,6 +98,9 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of access + if self.access: + _dict["access"] = self.access.to_dict() # override the default output from pydantic by calling `to_dict()` of extensions if self.extensions: _dict["extensions"] = self.extensions.to_dict() @@ -113,9 +119,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in nodepools (list) _items = [] if self.nodepools: - for _item in self.nodepools: - if _item: - _items.append(_item.to_dict()) + for _item_nodepools in self.nodepools: + if _item_nodepools: + _items.append(_item_nodepools.to_dict()) _dict["nodepools"] = _items # override the default output from pydantic by calling `to_dict()` of status if self.status: @@ -133,6 +139,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { + "access": Access.from_dict(obj["access"]) if obj.get("access") is not None else None, "extensions": Extension.from_dict(obj["extensions"]) if obj.get("extensions") is not None else None, "hibernation": ( Hibernation.from_dict(obj["hibernation"]) if obj.get("hibernation") is not None else None diff --git a/services/ske/src/stackit/ske/models/cluster_error.py b/services/ske/src/stackit/ske/models/cluster_error.py index 4de3df059..c75d8ec84 100644 --- a/services/ske/src/stackit/ske/models/cluster_error.py +++ b/services/ske/src/stackit/ske/models/cluster_error.py @@ -28,7 +28,7 @@ class ClusterError(BaseModel): code: Optional[StrictStr] = Field( default=None, - description='Possible values: `"SKE_OBSERVABILITY_INSTANCE_NOT_FOUND"`, `"SKE_DNS_ZONE_NOT_FOUND"`, `"SKE_NODE_NO_VALID_HOST_FOUND"`, `"SKE_NODE_MISCONFIGURED_PDB"`, `"SKE_NODE_MACHINE_TYPE_NOT_FOUND"`, `"SKE_INFRA_SNA_NETWORK_NOT_FOUND"`, `"SKE_FETCHING_ERRORS_NOT_POSSIBLE"`', + description='Possible values: `"SKE_INFRA_SNA_NETWORK_NOT_FOUND"`, `"SKE_INFRA_SNA_NETWORK_NO_ROUTER"`, `"SKE_NODE_NO_VALID_HOST_FOUND"`, `"SKE_NODE_MISCONFIGURED_PDB"`, `"SKE_NODE_MACHINE_TYPE_NOT_FOUND"`, `"SKE_NETWORK_NO_DNS_CONFIGURED"`, `"SKE_NETWORK_NO_AVAILABLE_IPS"`, `"SKE_NODE_MEMORY_PRESSURE"`, `"SKE_NODE_DISK_PRESSURE"`, `"SKE_NODE_PID_PRESSURE"`, `"SKE_OBSERVABILITY_INSTANCE_NOT_FOUND"`, `"SKE_OBSERVABILITY_INSTANCE_NOT_READY"`, `"SKE_DNS_ZONE_NOT_FOUND"`, `"SKE_FETCHING_ERRORS_NOT_POSSIBLE"`', ) message: Optional[StrictStr] = None __properties: ClassVar[List[str]] = ["code", "message"] diff --git a/services/ske/src/stackit/ske/models/cluster_status.py b/services/ske/src/stackit/ske/models/cluster_status.py index 08dd58ad4..508b36dbe 100644 --- a/services/ske/src/stackit/ske/models/cluster_status.py +++ b/services/ske/src/stackit/ske/models/cluster_status.py @@ -130,9 +130,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in errors (list) _items = [] if self.errors: - for _item in self.errors: - if _item: - _items.append(_item.to_dict()) + for _item_errors in self.errors: + if _item_errors: + _items.append(_item_errors.to_dict()) _dict["errors"] = _items return _dict diff --git a/services/ske/src/stackit/ske/models/create_or_update_cluster_payload.py b/services/ske/src/stackit/ske/models/create_or_update_cluster_payload.py index 6b120c4bc..6e3272251 100644 --- a/services/ske/src/stackit/ske/models/create_or_update_cluster_payload.py +++ b/services/ske/src/stackit/ske/models/create_or_update_cluster_payload.py @@ -20,6 +20,7 @@ from pydantic import BaseModel, ConfigDict, Field from typing_extensions import Annotated, Self +from stackit.ske.models.access import Access from stackit.ske.models.cluster_status import ClusterStatus from stackit.ske.models.extension import Extension from stackit.ske.models.hibernation import Hibernation @@ -34,6 +35,7 @@ class CreateOrUpdateClusterPayload(BaseModel): CreateOrUpdateClusterPayload """ # noqa: E501 + access: Optional[Access] = None extensions: Optional[Extension] = None hibernation: Optional[Hibernation] = None kubernetes: Kubernetes @@ -42,6 +44,7 @@ class CreateOrUpdateClusterPayload(BaseModel): nodepools: Annotated[List[Nodepool], Field(min_length=1, max_length=50)] status: Optional[ClusterStatus] = None __properties: ClassVar[List[str]] = [ + "access", "extensions", "hibernation", "kubernetes", @@ -88,6 +91,9 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of access + if self.access: + _dict["access"] = self.access.to_dict() # override the default output from pydantic by calling `to_dict()` of extensions if self.extensions: _dict["extensions"] = self.extensions.to_dict() @@ -106,9 +112,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in nodepools (list) _items = [] if self.nodepools: - for _item in self.nodepools: - if _item: - _items.append(_item.to_dict()) + for _item_nodepools in self.nodepools: + if _item_nodepools: + _items.append(_item_nodepools.to_dict()) _dict["nodepools"] = _items # override the default output from pydantic by calling `to_dict()` of status if self.status: @@ -126,6 +132,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { + "access": Access.from_dict(obj["access"]) if obj.get("access") is not None else None, "extensions": Extension.from_dict(obj["extensions"]) if obj.get("extensions") is not None else None, "hibernation": ( Hibernation.from_dict(obj["hibernation"]) if obj.get("hibernation") is not None else None diff --git a/services/ske/src/stackit/ske/models/hibernation.py b/services/ske/src/stackit/ske/models/hibernation.py index c5e2ea0e5..8adfc480e 100644 --- a/services/ske/src/stackit/ske/models/hibernation.py +++ b/services/ske/src/stackit/ske/models/hibernation.py @@ -71,9 +71,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in schedules (list) _items = [] if self.schedules: - for _item in self.schedules: - if _item: - _items.append(_item.to_dict()) + for _item_schedules in self.schedules: + if _item_schedules: + _items.append(_item_schedules.to_dict()) _dict["schedules"] = _items return _dict diff --git a/services/ske/src/stackit/ske/models/idp_kubeconfig.py b/services/ske/src/stackit/ske/models/idp_kubeconfig.py new file mode 100644 index 000000000..8714cfbda --- /dev/null +++ b/services/ske/src/stackit/ske/models/idp_kubeconfig.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + STACKIT Kubernetes Engine API + + The SKE API provides endpoints to create, update or delete clusters within STACKIT projects and to trigger further cluster management tasks. + + The version of the OpenAPI document: 2.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations + +import json +import pprint +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing_extensions import Self + + +class IDPKubeconfig(BaseModel): + """ + IDPKubeconfig + """ # noqa: E501 + + kubeconfig: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["kubeconfig"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of IDPKubeconfig from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of IDPKubeconfig from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"kubeconfig": obj.get("kubeconfig")}) + return _obj diff --git a/services/ske/src/stackit/ske/models/list_clusters_response.py b/services/ske/src/stackit/ske/models/list_clusters_response.py index 3fdd7ea60..428e1b0ed 100644 --- a/services/ske/src/stackit/ske/models/list_clusters_response.py +++ b/services/ske/src/stackit/ske/models/list_clusters_response.py @@ -71,9 +71,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in items (list) _items = [] if self.items: - for _item in self.items: - if _item: - _items.append(_item.to_dict()) + for _item_items in self.items: + if _item_items: + _items.append(_item_items.to_dict()) _dict["items"] = _items return _dict diff --git a/services/ske/src/stackit/ske/models/machine_image.py b/services/ske/src/stackit/ske/models/machine_image.py index 1ce1ad7c4..082d9b4a9 100644 --- a/services/ske/src/stackit/ske/models/machine_image.py +++ b/services/ske/src/stackit/ske/models/machine_image.py @@ -72,9 +72,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in versions (list) _items = [] if self.versions: - for _item in self.versions: - if _item: - _items.append(_item.to_dict()) + for _item_versions in self.versions: + if _item_versions: + _items.append(_item_versions.to_dict()) _dict["versions"] = _items return _dict diff --git a/services/ske/src/stackit/ske/models/machine_image_version.py b/services/ske/src/stackit/ske/models/machine_image_version.py index 862f7e3bf..489c28ab0 100644 --- a/services/ske/src/stackit/ske/models/machine_image_version.py +++ b/services/ske/src/stackit/ske/models/machine_image_version.py @@ -99,9 +99,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in cri (list) _items = [] if self.cri: - for _item in self.cri: - if _item: - _items.append(_item.to_dict()) + for _item_cri in self.cri: + if _item_cri: + _items.append(_item_cri.to_dict()) _dict["cri"] = _items return _dict diff --git a/services/ske/src/stackit/ske/models/nodepool.py b/services/ske/src/stackit/ske/models/nodepool.py index 019ffb8f1..1ff8e7e54 100644 --- a/services/ske/src/stackit/ske/models/nodepool.py +++ b/services/ske/src/stackit/ske/models/nodepool.py @@ -123,9 +123,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in taints (list) _items = [] if self.taints: - for _item in self.taints: - if _item: - _items.append(_item.to_dict()) + for _item_taints in self.taints: + if _item_taints: + _items.append(_item_taints.to_dict()) _dict["taints"] = _items # override the default output from pydantic by calling `to_dict()` of volume if self.volume: diff --git a/services/ske/src/stackit/ske/models/provider_options.py b/services/ske/src/stackit/ske/models/provider_options.py index 5e30509c4..125fdeafc 100644 --- a/services/ske/src/stackit/ske/models/provider_options.py +++ b/services/ske/src/stackit/ske/models/provider_options.py @@ -85,37 +85,37 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of each item in availability_zones (list) _items = [] if self.availability_zones: - for _item in self.availability_zones: - if _item: - _items.append(_item.to_dict()) + for _item_availability_zones in self.availability_zones: + if _item_availability_zones: + _items.append(_item_availability_zones.to_dict()) _dict["availabilityZones"] = _items # override the default output from pydantic by calling `to_dict()` of each item in kubernetes_versions (list) _items = [] if self.kubernetes_versions: - for _item in self.kubernetes_versions: - if _item: - _items.append(_item.to_dict()) + for _item_kubernetes_versions in self.kubernetes_versions: + if _item_kubernetes_versions: + _items.append(_item_kubernetes_versions.to_dict()) _dict["kubernetesVersions"] = _items # override the default output from pydantic by calling `to_dict()` of each item in machine_images (list) _items = [] if self.machine_images: - for _item in self.machine_images: - if _item: - _items.append(_item.to_dict()) + for _item_machine_images in self.machine_images: + if _item_machine_images: + _items.append(_item_machine_images.to_dict()) _dict["machineImages"] = _items # override the default output from pydantic by calling `to_dict()` of each item in machine_types (list) _items = [] if self.machine_types: - for _item in self.machine_types: - if _item: - _items.append(_item.to_dict()) + for _item_machine_types in self.machine_types: + if _item_machine_types: + _items.append(_item_machine_types.to_dict()) _dict["machineTypes"] = _items # override the default output from pydantic by calling `to_dict()` of each item in volume_types (list) _items = [] if self.volume_types: - for _item in self.volume_types: - if _item: - _items.append(_item.to_dict()) + for _item_volume_types in self.volume_types: + if _item_volume_types: + _items.append(_item_volume_types.to_dict()) _dict["volumeTypes"] = _items return _dict diff --git a/services/ske/src/stackit/ske/rest.py b/services/ske/src/stackit/ske/rest.py index 85936df6c..27074d05f 100644 --- a/services/ske/src/stackit/ske/rest.py +++ b/services/ske/src/stackit/ske/rest.py @@ -38,12 +38,17 @@ def read(self): self.data = self.response.content return self.data + @property + def headers(self): + """Returns a dictionary of response headers.""" + return self.response.headers + def getheaders(self): - """Returns a dictionary of the response headers.""" + """Returns a dictionary of the response headers; use ``headers`` instead.""" return self.response.headers def getheader(self, name, default=None): - """Returns a given response header.""" + """Returns a given response header; use ``headers.get()`` instead.""" return self.response.headers.get(name, default) @@ -93,6 +98,7 @@ def request(self, method, url, headers=None, body=None, post_params=None, _reque url, data=request_body, headers=headers, + timeout=_request_timeout, ) elif content_type == "application/x-www-form-urlencoded": r = self.session.request( @@ -100,6 +106,7 @@ def request(self, method, url, headers=None, body=None, post_params=None, _reque url, params=post_params, headers=headers, + timeout=_request_timeout, ) elif content_type == "multipart/form-data": # must del headers['Content-Type'], or the correct @@ -113,6 +120,7 @@ def request(self, method, url, headers=None, body=None, post_params=None, _reque url, files=post_params, headers=headers, + timeout=_request_timeout, ) # Pass a `string` parameter directly in the body to support # other content types than JSON when `body` argument is @@ -123,10 +131,17 @@ def request(self, method, url, headers=None, body=None, post_params=None, _reque url, data=body, headers=headers, + timeout=_request_timeout, ) elif headers["Content-Type"].startswith("text/") and isinstance(body, bool): request_body = "true" if body else "false" - r = self.session.request(method, url, data=request_body, headers=headers) + r = self.session.request( + method, + url, + data=request_body, + headers=headers, + timeout=_request_timeout, + ) else: # Cannot generate the request from given parameters msg = """Cannot prepare a request message for provided @@ -140,6 +155,7 @@ def request(self, method, url, headers=None, body=None, post_params=None, _reque url, params={}, headers=headers, + timeout=_request_timeout, ) except requests.exceptions.SSLError as e: msg = "\n".join([type(e).__name__, str(e)])