diff --git a/services/ske/oas_commit b/services/ske/oas_commit index a886b4d4a..abd8d51b0 100644 --- a/services/ske/oas_commit +++ b/services/ske/oas_commit @@ -1 +1 @@ -ea0931a6f93703c990517136e0d4c7a88455b282 +46f03c1468dd453695c05e72c088a6bfb5a4bbab diff --git a/services/ske/src/stackit/ske/__init__.py b/services/ske/src/stackit/ske/__init__.py index 8680e736f..dca71287b 100644 --- a/services/ske/src/stackit/ske/__init__.py +++ b/services/ske/src/stackit/ske/__init__.py @@ -30,8 +30,10 @@ "ACL", "Access", "AccessScope", + "ApplicationLoadBalancer", "Audit", "AvailabilityZone", + "CNI", "CRI", "Cluster", "ClusterError", @@ -93,6 +95,9 @@ # import models into sdk package from stackit.ske.models.acl import ACL as ACL +from stackit.ske.models.application_load_balancer import ( + ApplicationLoadBalancer as ApplicationLoadBalancer, +) from stackit.ske.models.audit import Audit as Audit from stackit.ske.models.availability_zone import AvailabilityZone as AvailabilityZone from stackit.ske.models.cluster import Cluster as Cluster @@ -101,6 +106,7 @@ from stackit.ske.models.cluster_status_state import ( ClusterStatusState as ClusterStatusState, ) +from stackit.ske.models.cni import CNI as CNI from stackit.ske.models.create_kubeconfig_payload import ( CreateKubeconfigPayload as CreateKubeconfigPayload, ) diff --git a/services/ske/src/stackit/ske/models/__init__.py b/services/ske/src/stackit/ske/models/__init__.py index 1f8c300cf..62b2800e5 100644 --- a/services/ske/src/stackit/ske/models/__init__.py +++ b/services/ske/src/stackit/ske/models/__init__.py @@ -17,12 +17,14 @@ # import models into model package from stackit.ske.models.acl import ACL +from stackit.ske.models.application_load_balancer import ApplicationLoadBalancer from stackit.ske.models.audit import Audit from stackit.ske.models.availability_zone import AvailabilityZone from stackit.ske.models.cluster import Cluster from stackit.ske.models.cluster_error import ClusterError from stackit.ske.models.cluster_status import ClusterStatus from stackit.ske.models.cluster_status_state import ClusterStatusState +from stackit.ske.models.cni import CNI from stackit.ske.models.create_kubeconfig_payload import CreateKubeconfigPayload from stackit.ske.models.create_or_update_cluster_payload import ( CreateOrUpdateClusterPayload, diff --git a/services/ske/src/stackit/ske/models/application_load_balancer.py b/services/ske/src/stackit/ske/models/application_load_balancer.py new file mode 100644 index 000000000..e2fc3185b --- /dev/null +++ b/services/ske/src/stackit/ske/models/application_load_balancer.py @@ -0,0 +1,84 @@ +# 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, Field, StrictBool +from pydantic_core import to_jsonable_python +from typing_extensions import Self + + +class ApplicationLoadBalancer(BaseModel): + """ + ApplicationLoadBalancer + """ # noqa: E501 + + enabled: StrictBool = Field( + description="Enables the application load balancer extension. ⚠️ Note: This feature is in private preview. Enabling application load balancer extension is only possible for enabled accounts. Otherwise the request will be rejected." + ) + __properties: ClassVar[List[str]] = ["enabled"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=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""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ApplicationLoadBalancer 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 ApplicationLoadBalancer from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"enabled": obj.get("enabled")}) + return _obj diff --git a/services/ske/src/stackit/ske/models/cluster.py b/services/ske/src/stackit/ske/models/cluster.py index f55d19465..827204107 100644 --- a/services/ske/src/stackit/ske/models/cluster.py +++ b/services/ske/src/stackit/ske/models/cluster.py @@ -18,7 +18,7 @@ import re # noqa: F401 from typing import Any, ClassVar, Dict, List, Optional, Set -from pydantic import BaseModel, ConfigDict, Field, field_validator +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from pydantic_core import to_jsonable_python from typing_extensions import Annotated, Self @@ -43,6 +43,10 @@ class Cluster(BaseModel): extensions: Optional[Extension] = None hibernation: Optional[Hibernation] = None kubernetes: Kubernetes + labels: Optional[Dict[str, StrictStr]] = Field( + default=None, + description="Labels are key-value pairs. Keys may contain domain prefix separated by a slash(/) and must begin with an alphanumerical character. Values may be empty and if not empty, they must begin and end with an alphanumerical character. Keys can be between 1-314 characters long, whereas values can be 0-63 characters long.", + ) maintenance: Optional[Maintenance] = None name: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=11)]] = Field( default=None, @@ -57,6 +61,7 @@ class Cluster(BaseModel): "extensions", "hibernation", "kubernetes", + "labels", "maintenance", "name", "network", @@ -170,6 +175,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: Hibernation.from_dict(obj["hibernation"]) if obj.get("hibernation") is not None else None ), "kubernetes": Kubernetes.from_dict(obj["kubernetes"]) if obj.get("kubernetes") is not None else None, + "labels": obj.get("labels"), "maintenance": ( Maintenance.from_dict(obj["maintenance"]) if obj.get("maintenance") is not None else None ), diff --git a/services/ske/src/stackit/ske/models/cni.py b/services/ske/src/stackit/ske/models/cni.py new file mode 100644 index 000000000..be84649e2 --- /dev/null +++ b/services/ske/src/stackit/ske/models/cni.py @@ -0,0 +1,82 @@ +# 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, Field +from pydantic_core import to_jsonable_python +from typing_extensions import Self + + +class CNI(BaseModel): + """ + CNI to use for the cluster. Only one type of CNI can be used. The type of CNI is immutable after creation. Defaults to calico + """ # noqa: E501 + + calico: Optional[Dict[str, Any]] = Field(default=None, description="configuration options for the Calico CNI") + __properties: ClassVar[List[str]] = ["calico"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=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""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CNI 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 CNI from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"calico": obj.get("calico")}) + return _obj 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 5fa2c6a5f..a48a5d2de 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 @@ -17,7 +17,7 @@ import pprint from typing import Any, ClassVar, Dict, List, Optional, Set -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, StrictStr from pydantic_core import to_jsonable_python from typing_extensions import Annotated, Self @@ -42,6 +42,10 @@ class CreateOrUpdateClusterPayload(BaseModel): extensions: Optional[Extension] = None hibernation: Optional[Hibernation] = None kubernetes: Kubernetes + labels: Optional[Dict[str, StrictStr]] = Field( + default=None, + description="Labels are key-value pairs. Keys may contain domain prefix separated by a slash(/) and must begin with an alphanumerical character. Values may be empty and if not empty, they must begin and end with an alphanumerical character. Keys can be between 1-314 characters long, whereas values can be 0-63 characters long.", + ) maintenance: Optional[Maintenance] = None network: Optional[Network] = None nodepools: Annotated[List[Nodepool], Field(min_length=1, max_length=50)] @@ -52,6 +56,7 @@ class CreateOrUpdateClusterPayload(BaseModel): "extensions", "hibernation", "kubernetes", + "labels", "maintenance", "network", "nodepools", @@ -146,6 +151,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: Hibernation.from_dict(obj["hibernation"]) if obj.get("hibernation") is not None else None ), "kubernetes": Kubernetes.from_dict(obj["kubernetes"]) if obj.get("kubernetes") is not None else None, + "labels": obj.get("labels"), "maintenance": ( Maintenance.from_dict(obj["maintenance"]) if obj.get("maintenance") is not None else None ), diff --git a/services/ske/src/stackit/ske/models/extension.py b/services/ske/src/stackit/ske/models/extension.py index 06885f0b1..4312d622e 100644 --- a/services/ske/src/stackit/ske/models/extension.py +++ b/services/ske/src/stackit/ske/models/extension.py @@ -17,11 +17,12 @@ import pprint from typing import Any, ClassVar, Dict, List, Optional, Set -from pydantic import BaseModel, ConfigDict +from pydantic import BaseModel, ConfigDict, Field from pydantic_core import to_jsonable_python from typing_extensions import Self from stackit.ske.models.acl import ACL +from stackit.ske.models.application_load_balancer import ApplicationLoadBalancer from stackit.ske.models.dns import DNS from stackit.ske.models.observability import Observability @@ -32,9 +33,10 @@ class Extension(BaseModel): """ # noqa: E501 acl: Optional[ACL] = None + application_load_balancer: Optional[ApplicationLoadBalancer] = Field(default=None, alias="applicationLoadBalancer") dns: Optional[DNS] = None observability: Optional[Observability] = None - __properties: ClassVar[List[str]] = ["acl", "dns", "observability"] + __properties: ClassVar[List[str]] = ["acl", "applicationLoadBalancer", "dns", "observability"] model_config = ConfigDict( validate_by_name=True, @@ -76,6 +78,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of acl if self.acl: _dict["acl"] = self.acl.to_dict() + # override the default output from pydantic by calling `to_dict()` of application_load_balancer + if self.application_load_balancer: + _dict["applicationLoadBalancer"] = self.application_load_balancer.to_dict() # override the default output from pydantic by calling `to_dict()` of dns if self.dns: _dict["dns"] = self.dns.to_dict() @@ -96,6 +101,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "acl": ACL.from_dict(obj["acl"]) if obj.get("acl") is not None else None, + "applicationLoadBalancer": ( + ApplicationLoadBalancer.from_dict(obj["applicationLoadBalancer"]) + if obj.get("applicationLoadBalancer") is not None + else None + ), "dns": DNS.from_dict(obj["dns"]) if obj.get("dns") is not None else None, "observability": ( Observability.from_dict(obj["observability"]) if obj.get("observability") is not None else None diff --git a/services/ske/src/stackit/ske/models/hibernation_schedule.py b/services/ske/src/stackit/ske/models/hibernation_schedule.py index 62a04baa3..1a3666128 100644 --- a/services/ske/src/stackit/ske/models/hibernation_schedule.py +++ b/services/ske/src/stackit/ske/models/hibernation_schedule.py @@ -40,11 +40,11 @@ def end_validate_regular_expression(cls, value): value = str(value) if not re.match( - r"(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\\d+(ns|us|µs|ms|s|m|h))+)|((((\\d+,)+\\d+|(\\d+(\\/|-)\\d+)|\\d+|\\*) ?){5,7})", + r"(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})", value, ): raise ValueError( - r"must validate the regular expression /(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\\d+(ns|us|µs|ms|s|m|h))+)|((((\\d+,)+\\d+|(\\d+(\\/|-)\\d+)|\\d+|\\*) ?){5,7})/" + r"must validate the regular expression /(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})/" ) return value @@ -55,11 +55,11 @@ def start_validate_regular_expression(cls, value): value = str(value) if not re.match( - r"(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\\d+(ns|us|µs|ms|s|m|h))+)|((((\\d+,)+\\d+|(\\d+(\\/|-)\\d+)|\\d+|\\*) ?){5,7})", + r"(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})", value, ): raise ValueError( - r"must validate the regular expression /(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\\d+(ns|us|µs|ms|s|m|h))+)|((((\\d+,)+\\d+|(\\d+(\\/|-)\\d+)|\\d+|\\*) ?){5,7})/" + r"must validate the regular expression /(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})/" ) return value 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 704e4797e..35136b96b 100644 --- a/services/ske/src/stackit/ske/models/machine_image_version.py +++ b/services/ske/src/stackit/ske/models/machine_image_version.py @@ -59,8 +59,13 @@ def version_validate_regular_expression(cls, value): if not isinstance(value, str): value = str(value) - if not re.match(r"^\d+\.\d+\.\d+$", value): - raise ValueError(r"must validate the regular expression /^\d+\.\d+\.\d+$/") + if not re.match( + r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", + value, + ): + raise ValueError( + r"must validate the regular expression /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/" + ) return value model_config = ConfigDict( diff --git a/services/ske/src/stackit/ske/models/network.py b/services/ske/src/stackit/ske/models/network.py index e40e3c90c..4ff701875 100644 --- a/services/ske/src/stackit/ske/models/network.py +++ b/services/ske/src/stackit/ske/models/network.py @@ -21,6 +21,7 @@ from pydantic_core import to_jsonable_python from typing_extensions import Self +from stackit.ske.models.cni import CNI from stackit.ske.models.v2_control_plane_network import V2ControlPlaneNetwork @@ -29,9 +30,10 @@ class Network(BaseModel): Network """ # noqa: E501 + cni: Optional[CNI] = None control_plane: Optional[V2ControlPlaneNetwork] = Field(default=None, alias="controlPlane") id: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["controlPlane", "id"] + __properties: ClassVar[List[str]] = ["cni", "controlPlane", "id"] model_config = ConfigDict( validate_by_name=True, @@ -70,6 +72,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 cni + if self.cni: + _dict["cni"] = self.cni.to_dict() # override the default output from pydantic by calling `to_dict()` of control_plane if self.control_plane: _dict["controlPlane"] = self.control_plane.to_dict() @@ -86,6 +91,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { + "cni": CNI.from_dict(obj["cni"]) if obj.get("cni") is not None else None, "controlPlane": ( V2ControlPlaneNetwork.from_dict(obj["controlPlane"]) if obj.get("controlPlane") is not None